linux c文件操作,Linux C 文件的輸入/輸出操作

10.1 文件I/O操作概述

在Linux系統中,文件I/O操作可以分為兩類,一類是基于文件描述符的I/O操作,另一類是基于數據流的I/O操作。

10.1.1 文件描述符簡介

在文件操作一章中,也經常提到文件描述符這個概念。所謂文件描述符,就是進程與打開的文件的一個橋梁,通過這個橋梁,才可以在進程中對這個文件進行讀寫等操作。

在Linux環境下,每打開一個磁盤文件,都會在內核中建立一個文件表項,文件表項中存儲著文件的狀態信息、存儲文件內容的緩沖區和當前文件的讀寫位置。如果同一磁盤文件打開了3次,就會創建3個這樣的文件表項(a,b和c),讀寫文件時,只會改變該文件表項中的文件讀寫位置。這3個文件表項存儲在一個文件表數組table[3]中,在這里table[0]=a,table[1]=b,table[2]=c。這個文件表的下標就稱之為文件描述符,將這個文件描述符存儲在一個數組中des[3]={0,1,2},那么,在進程中就可以通過這個des數組下標引用文件表項。也就是說,通過文件描述符就可以訪問到這個磁盤文件。

10.1.2 數據流概述

從數據操作方式這個角度來說,Linux系統中的文件(無論是普通文件還是設備文件)可以看做是數據流。對文件進行操作之前,必須先調用標準I/O庫函數fopen()將數據流打開。打開數據流之后,就可以對數據流進行輸入和輸出的操作。

標準I/O庫函數是C語言中所特有的用于高級接口的函數,這些庫函數存放在C語言的stdio.h頭文件中,因此這些用于數據流的I/O操作函數不僅適用于Linux系統,還適用于其他的操作系統。由此可見,此庫函數的引用大大增加了程序的移植性。

要對數據流進行讀寫操作時,需要標準I/O庫函數和FILE類型的文件指針一起來實現。這個文件指針石達開數據流時返回的指針,該指針用來表示要操作的數據流。

當執行程序時,有3個數據流不需要特定的函數進行打開的操作,他們會自動打開。這3個數據流是標準輸入、標準輸出和標準錯誤輸出。他們是自動打開的,當不使用時,也會自動關閉。

然而,調用標準I/O庫函數fopen()打開的數據流,在對數據流進行操作后,需要調用fclose()函數將其關閉。fclose()函數在關閉數據流之前,會清空在操作過程中分配的緩沖區并保存數據信息。

10.2 基于文件描述符的I/O操作

10.2.1 文件的打開與關閉

1)open()函數

#include

#include

#include

int open(const char *pathname, int flags)

int open(const char *pathname, int flags, mode_t mode)

int creat(const char *pathname, mode_t mode)

上述的兩個open()函數和一個creat()函數在調用成功時,都會返回其新分配的文件描述符;否則返值為-1,并設置適當的error。

2)close()函數

#incldue

int close(int fd)

當一個進程終止時,內核對該進程的所有尚未關閉的文件描述符調用close()函數關閉,所以即使用戶程序不調用close()函數,在終止時內核也會自動關閉它打開的所有文件。但是,對于網絡服務器這種一直運行的程序,文件描述符一定要及時關閉,否則隨著打開的文件越來越多,會占用大量文件描述符和系統資源。

有函數open()返回的文件描述符一定是該進程尚未使用的最小描述符。由于程序啟動時自動打開標準輸入、標準輸出和標準錯誤輸出,因此文件描述符0,1,2會存在,那么第一次調用open()函數打開文件時返回的文件描述符通常會是3,再調用open()函數就會返回4.可以利用這一點在標準輸入、標準輸出或標準錯誤輸出上打開一個新文件,是想重定向的功能。例如,首先調用close()函數關閉文件描述符1,然后調用open()函數打開一個常規文件,則一定會返回文件描述符1,這是標準輸出就不再是終端,而是一個常規文件了,再調用printf()函數就不打印到屏幕上,而是寫到這個文件中了。在文件操作一章中講到的dup2()函數就是另外一種在指定的文件描述符上打開文件的方法。

10.2.2 文件的讀寫操作

1)read()函數

#include

ssize_t read(int fd, void *buf, size_t count)

2)write()函數

#include

ssize_t write(int fd, const void *buf, size_t count)

10.2.3 文件的定位

每個文件都記錄著當前讀寫位置,打開文件時讀寫位置是0,表示文件開頭,通常讀寫多少個自己就會將讀寫位置往后移多少個字節。

以O_APPEND方式打開文件,每次寫操作都會在文件末尾追加數據,然后間讀寫位置移動到新的文件末尾。

1)lseek()函數

lseek()函數可以移動當前讀寫位置,通常稱為偏移量,該函數的定義形式如下:

#include

#include

off_t lseek(int fildes, off_t offset, int whence)

10.3 基于數據流的I/O操作

10.3.1 文件的打開與關閉

在操作文件之前要用fopen()函數打開文件,操作結束后,要用fclose()函數關閉文件。

1)fopen()函數

#include

FILE *foepn(cosnt char *path, cosnt char *mode)

2)fclose()函數

#include

int fclose(FILE *fp)

10.3.2 字符輸入/輸出

1)fgetc()函數

fgetc()函數從指定的文件中讀一個字節,該函數的定義形式如下:

#include

int fgetc(FILE *stream)

在程序中,偶爾會遇到getchar()函數,也是用于讀取一個字節,但它是從標準輸入讀一個字節。在程序中調用getchar()函數相當于調動fgetc(stdin)

在使用fgetc()函數時需要注意一下幾點:

①調用fgetc()函數時,指定的文件的打開方式必須是可讀的。

②函數fgetc()調用成功時,返回的是讀到的字節,應該為unsigned char,但fgetc()函數在原型中返回值類型時int,原因在于函數調用出錯或讀到文件末尾時fgetc()會返回EOF,即-1,保存在int型的返回值是0xffffffff,如果讀到字節0xff,由unsigned char型轉換int 型時0x000000ff,只有規定返回值是int型才能把這種情況區分開,如果規定返回值是unsigned char型,那么當返回值是0xff時則無法區分到底是EOF還是字節0xff。

2)fputc()函數

#include

int fputc(int c, FILE *stream)

10.3.3 字符串輸入/輸出

1)fgets()函數

#include

char *fgets(char *s, int size, FILE *stream)

對于fgets()函數而言,'\n'是一個特別的字符,作為結束符;而'\0'并無任何特別之處,只用作普通字符串讀入。正因為'\0'作為一個普通的字符串,因此無法判斷緩沖區中的'\0'究竟是從文件讀上來的字符還是有fgets()函數自主添加的結束符,所以fgets()函數只用于讀文本文件而不提倡讀二進制文件,并且文本文件中的所有字符串不能有'\0'。

2)fputs()

#include

int fputs(const char *s, FILE *stream)

緩沖區s中保存的是以'\0'結尾的字符串,fputs()將該字符串寫入文件stream,但并不寫入結尾的'\0',且字符串中可以有'\n',也可以沒有'\n'。

10.3.4 數據塊輸入/輸出

1)fread()和fwrite()函數

#include

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)

size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)

10.3.5 格式化輸入/輸出

所謂格式化輸入/輸出,就是按照一定的格式將數據進行輸入/輸出操作。在程序中經常用到的printf()函數和scanf()函數是用于對終端設備文件的讀寫操作,這兩個函數被稱為格式化輸入/輸出,因為在使用這兩個函數時,需要制定讀寫數據的數據類型并按照一定的格式進行讀寫。

1)格式化輸入函數

#include

int printf(const char *format,...)

int fprintf(FILE *stream, const char *format)

int sprintf(char *str, size_t size, const char *format,...)

2)格式化輸出函數

#include

int scanf(const char *format,...)

int fscanf(FILE *stream, const char *format,...)

int sscanf(const char *str, const char *format,...)

10.3.6 操作讀寫位置的函數

1)fseek()函數

#inlcude

int fseek(FILE *stream, long offset, int whence)

函數fseek()的作用是用來移動文件內部位置指針。

2)ftell()函數

#inlcude

long ftell(FILE *stream)

ftell()函數的作用是得到stream指定的流式文件中的位置。

3)rewind()函數

void rewind(FILE *stream)

rewind()函數的作用是使位置指針重新返回文件的開頭,該函數沒有返回值。

10.3.7 C標準的I/O緩沖區

C標準庫在調用fopen()函數時,都會給此文件分配一個I/O緩沖區,可以加速讀寫操作,原因在于用戶程序需要調用C標準I/O庫函數(如fread()、fwrite()等基于文件流I/O操作)讀寫文件,當緩沖區裝滿后,再由系統調用的I/O函數(如read()、write()等基于文件描述符的I/O操作)把讀寫請求傳給內核,最終由內核驅動磁盤或設備完成I/O操作。

由此看來,為文件分配的內存緩沖區大小,直接影響到實際操作外村設備的次數,內存中為未見分配的緩沖區越大,操作外存的次數會越小,因此讀寫數據的速度會越來越快,效率就會隨之增高。

然而,有時用戶程序等不及將緩沖區都裝滿之后再傳給內核,進行I/O操作,而是希望把I/O緩沖區中的數據立刻傳給內核,讓內核寫回設備,這種行為叫做flush操作,對應的庫函數是fflush()。

C標準庫的I/O緩沖區有全緩沖、行緩沖和無緩沖3種類型。

1)全緩沖:如果緩沖區寫滿了,就寫回內核。普通文件通常是全緩沖的。

2)行緩沖:如果用戶程序寫的數據中有'\n',就把這一行寫回內核,或者緩沖區寫滿后就寫回內核。標準輸入和標準輸出對應中斷設備時通常是行緩沖。

3)無緩沖:用戶程序每次調庫函數做寫操作都要通過系統調用寫回內核。標準錯誤輸出通常是無緩沖的。這樣用戶程序產生的錯誤信息就可以盡快輸出到設備。

使用緩沖區時,會使用到如下兩類操作,一個是設置緩沖區屬性,另外一個是清空緩沖區。

4)設置緩沖區屬性

#include

void setbuf(FILE *stream, char *buf)

void setbuffer(FILE *stream, char *buf, size_t size)

void setlinebuf(FILE *stream)

int setvbuf(FILE *stream, char *buf, int mode, size_t size)

setbuf()函數主要實現了為參數buf所指定的緩沖區設置大小。此函數中,設定緩沖區大小的值只有兩個,一個是常數BUFSIZ,另一個是NULL。當定義值為BUFSIZ時,代表設置緩沖區為全緩沖;若為NULL,則代表設置緩沖區為無緩沖形式。

setbuffer()與setbuf()功能相同,只是setbuffer()函數可以任意指定緩沖區大小為size

setlinebuf()函數實現了將stream指向的緩沖區設置為行緩沖。

setvbuf()函數融合了上述3種函數的功能,既可以設置緩沖區的任意大小size,也可以設置緩沖區的任意類型,如mode參數取值為_IOFBF(全緩沖類型)、_IOLBF(行緩沖類型)或_IONBF(無緩沖類型)。

5)清空緩沖區

#include

int fflush(FILE *stream)

fflush()函數實現將緩沖區中的尚未寫入文件的數據強制性地寫進stream所指定的文件中,然后清空緩沖區。如果stream為NULL,此函數會將所有打開的文件數據更新。

10.4 小結

本章主要介紹了Linux系統下的文件I/O操作。在Linux系統下存在兩種文件I/O操作,一種是基于文件描述符的I/O操作,這里面的I/O操作都是Linux系統中提供并直接作用于內核的,是非緩沖的I/O操作;另一種I/O操作是基于數據流的I/O操作,是由C語言的stdio庫所提供的,需要在內存中開辟一塊緩沖區,在緩沖區中進行快速地讀寫操作。本章主要結合典型實例介紹了上述兩種I/O操作方式對文件的打開、關閉、讀、寫、文件定位等操作。

注:感覺本文10.3.5之前的內容對我有用,讓我大概明白了基于數據流的文件I/O和基于文件描述符的文件I/O操作之間的區別。但是如果在給出其中的從操作函數之后給出一些實例就更好了。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/281617.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/281617.shtml
英文地址,請注明出處:http://en.pswp.cn/news/281617.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

個人中心標簽頁導航

新頁面userbase.html,用<ul ><li role"presentation"> 實現標簽頁導航。<ul class"nav nav-tabs"> <li role"presentation"><a href"#">Home</a></li> <li role"presentation&qu…

智慧城市免費WiFi覆蓋怎么實施?武邑開啟智慧生活模式

“真沒想到武邑這個國家級貧困縣也能夠隨地使用無線網絡&#xff0c;我初次考察就喜歡上了這里。”準備前來武邑縣投資的客商王先生說。日前&#xff0c;隨著縣城廣場、商場等公共場所的免費WiFi覆蓋&#xff0c;及移動電子商務借勢O2O的快速發展&#xff0c;衡水市武邑縣正在逐…

Uno開發的小游戲

大家好&#xff0c;我是沙漠盡頭的狼。剛在微信群里逛&#xff0c;有網友發了Uno的在線小游戲&#xff0c;站長覺得不錯&#xff0c;簡單分享下&#xff1a;群聊漲見識Uno是什么&#xff1f;使用 C# 和 WinUI 實現像素完美的多平臺應用程序&#xff0c;用于構建適用于 Windows、…

sqlplus命令行登錄oracle數據庫的N種方法盤點

歡迎訪問我的個人博客IT廢柴&#xff0c;本文永久鏈接移至&#xff1a;sqlplus命令行登錄oracle數據庫的N種方法盤點 sqlplus有幾種登陸方式Oracle數據庫&#xff0c; 比如&#xff1a; 1.以操作系統權限認證的oracle sys管理員登陸 C: > sqlplus "/as sysdba" 2…

拉美光伏新興市場熱潮將至

國際油價下滑對油氣生產國的影響是不言而喻的&#xff0c;受此拖累&#xff0c;可再生能源產業發展也承受了一定壓力。然而&#xff0c;在多國擁有油氣資源的拉美地區&#xff0c;情況卻恰恰相反&#xff0c;許多國家的可再生能源產業非但沒有受低油價拖累&#xff0c;反而快速…

linux下常見生產腳本,不看后悔的Linux生產服務器Shell腳本分享(2)

一、MySQL的熱備份腳本這是MySQL的備份方式之一&#xff0c;腳本如下&#xff1a;#!/bin/bashPATH/usr/local/sbin:/usr/bin:/bin# The Directory of BackupBACKDIR/usr/mysql_backup# The Password of MySQLROOTPASSpassword# Remake the Directory of Backuprm -rf $BACKDIRm…

兄弟連學python——MongoDB相關

1.常用的命令 show dbs 顯示數據庫列表use dbname 進入dbname數據庫&#xff0c;大小寫敏感&#xff0c;沒有這個數據庫也不要緊show collections 顯示數據庫中的集合&#xff0c;相當于表格2.創建&新增 db.users.save({"name":"lecaf"}) …

WPF-12 路由事件之二

WPF 為我們提供了許多不同的事件處理機制——它們是冒泡、隧道和直接的。這些都稱為路由事件直接事件直接在事件源上處理&#xff0c;這個有點像WinForms中的按鈕OnClick事件&#xff0c;直接在事件處理程序中處理業務冒泡事件當事件沒有被元素&#xff08;比如一個文本框&…

對01背包的分析與理解(圖文)

首先謝謝Christal_R的文章(點擊轉到鏈接)讓我學會01背包 本文較長&#xff0c;但是長也意味著比較詳細&#xff0c;希望您可以耐心讀完。 題目: 現在有一個背包(容器),它的體積(容量)為V,現在有N種物品(每個物品只有一個),每個物品的價值W[i]和占用空間C[i]都會由輸入給出,現在…

linux內核源碼剖析 博客,【Linux內存源碼分析】頁面遷移

頁面遷移其實是伙伴管理算法中的一部分&#xff0c;鑒于其特殊性&#xff0c;特地另行分析。它是2007年的時候&#xff0c;2.6.24內核版本開發時&#xff0c;新增碎片減少策略(the fragmentation reduction strategy)所引入的。該策略也稱之為反碎片技術(anti-gragmentation)。…

360的下一代SOC是這個樣子的

幾乎所有大型企業或機構的IT系統中&#xff0c;都會有安全運營中心(SOC)&#xff0c;它是網絡安全防護體系從設備部署到系統建設&#xff0c;再到統一管理&#xff0c;這一發展過程的自然產物。但在國內的實際應用中&#xff0c;SOC的問題多多。 首先是數據類型不全&#xff0c…

【轉載】利用scipy.misc等庫對jpg以及png等圖像數據預處理(用于深度學習喂數據)...

http://blog.csdn.net/qq_16949707/article/details/56306720 轉載于:https://www.cnblogs.com/tenderwx/p/8057599.html

2018年下半年網絡公式考試案例分析真題

閱讀以下說明&#xff0c;回答問題1至問題3&#xff0c;將解答填入答題紙對應的解答欄內。【說明】某公司網絡劃分為兩個子網&#xff0c;其中設備A是DHCP服務器&#xff0c;如圖3-1所示。 【問題1】(6分&#xff0c;每空2分)DHCP在分配IP地址時使用 (1) 的方式&#xff0c; 而…

哪一個不是linux常用的shell,Linux下查看使用的是哪種shell的方法匯總

查看當前發行版可以使用的shell復制代碼代碼如下:[rootlocalhost ~]$ cat /etc/shells/bin/sh/bin/bash/sbin/nologin查看當前使用的shell方法一、最常用的查看shell的命令&#xff0c;但不能實時反映當前shell復制代碼代碼如下:[rootlocalhost ~]$ echo $SHELL/bin/bash二、下…

企業建設呼叫中心需要考慮哪些因素

呼叫中心發展至今&#xff0c;它的意義早已不是90年代末,只是簡單地解決客戶客服系統的要求。現在的呼叫中心有了新的使命&#xff0c;比如拓展成為一個信息服務中心&#xff0c;或者成為一個營銷中心。客戶如何能通過這樣的手段&#xff0c;使企業與其他的企業之間形成差異化的…

【單片機入門】(三)應用層軟件開發的單片機學習之路-----UART串口通訊和c#交互...

本文由網友投稿。作者&#xff1a;陳顯達原文標題&#xff1a;【單片機入門】(三)應用層軟件開發的單片機學習之路-----UART串口通訊和c#交互原文鏈接&#xff1a;https://www.cnblogs.com/1996-Chinese-Chen/p/16826558.html引言在第一章博客中&#xff0c;我們講了Arduino對E…

linux中使用yum的優點,linux – 自動“yum update”以保證服務器安全 – 優點和缺點?...

這取決于根據我使用CentOS的經驗,它非常安全,因為您只使用CentOS基本存儲庫.您是否應該偶爾嘗試更新失敗…是…在您應該期望出現故障的硬盤驅動器或偶爾出現故障的CPU的同一級別上.您永遠不會有太多備份. &#x1f642;關于自動更新的好處是,您可以比手動修補更快(因此更安全).…

高能力成熟度軟件企業中軟件質量工程師的職責

隨著科學技術的不斷發展進步&#xff0c;企業之間的競爭越來越激烈。軟件企業要想在競爭中發展生存&#xff0c;提高軟件產品質量已成為必要條件。在一些高能力成熟度軟件企業中&#xff0c;專門成立了質量保證和控制職能部門&#xff0c;起著提高項目管理透明性和確保軟件產品…

存儲過程和函數的區別

存儲過程和函數的區別存儲過程和函數目的是為了 可重復地 執行操作數據庫的sql語句的集合。區別是寫法和調用上。寫法上&#xff1a;存儲過程的參數列表可以有輸入參數、輸出參數、可輸入輸出的參數&#xff1b;函數的參數列表只有輸入參數&#xff0c;并且有return <返回值…

機器學習案例丨基于廣泛和深入的推薦 - 餐廳評級預測

點擊上方藍字關注我們&#xff08;本文閱讀時間&#xff1a;18分鐘&#xff09;Microsoft Azure Machine Learning Studio 是微軟強大的機器學習平臺&#xff0c;在設計器中&#xff0c;微軟內置了15個場景案例&#xff0c;但網上似乎沒有對這15個案例深度刨析的分析資料&#…