目錄
1、标準 I/O 和檔案 I/O 的差別
2、标準輸入、标準輸出和标準錯誤
3、fopen()函數
4、fclose()函數
5、fread()函數
6、fwrite()函數
7、fseek()函數
8、ftell()函數
9、feof()函數
10、ferror()函數
11、clearerr()函數
12、stdio緩沖區
12.1、setvbuf()函數
12.2、setbuf()函數
12.3、setbuffer()函數
12.4、fflush()函數
12.5、重新整理 stdio 緩沖區
13、檔案描述符與 FILE 指針互轉
13.1、fileno()函數
13.2、fdopen()函數
1、标準 I/O 和檔案 I/O 的差別
1) 标準 I/O 是标準 C 庫函數,而檔案 I/O 則是 Linux系統調用;
2) 标準 I/O 是由檔案 I/O 封裝而來,标準 I/O 内部實際上是調用檔案 I/O 來完成實際操作的;
3) 可移植性:标準 I/O 相比于檔案 I/O 具有更好的可移植性,通常對于不同的作業系統,其核心向應用層提供的系統調用往往都是不同;而對于标準 I/O 來說,由于很多作業系統都實作了标準 I/O 庫,标準 I/O 庫在不同的作業系統之間其接口定義幾乎是一樣的,是以标準 I/O 在不同作業系統之間相比于檔案 I/O 具有更好的可移植性。
4)性能: 标準 I/O 庫在使用者空間維護了自己的 stdio 緩沖區, 是以标準 I/O 是帶有緩存的,而檔案 I/O 在使用者空間是不帶有緩存的,是以在性能、效率上,标準 I/O 要優于檔案 I/O。
2、标準輸入、标準輸出和标準錯誤
檔案 I/O 中,可以使用 STDIN_FILENO、 STDOUT_FILENO、 STDERR_FILENO來表示标準輸入、标準輸出和标準錯誤。
#include <unistd.h>
/* Standard file descriptors. */
#define STDIN_FILENO 0 /* Standard input. */
#define STDOUT_FILENO1 /* Standard output. */
#define STDERR_FILENO2 /* Standard error output. */
标準 I/O 中,可以使用 stdin、 stdout、 stderr 來表示标準輸入、标準輸出和标準錯誤。
#include <stdio.h>
/* Standard streams. */
extern struct _IO_FILE *stdin; /* Standard input stream. */
extern struct _IO_FILE *stdout; /* Standard output stream. */
extern struct _IO_FILE *stderr; /* Standard error output stream. */
/* C89/C99 say they're macros. Make them happy. */
#define stdin stdin
#define stdout stdout
#define stderr stderr
3、fopen()函數
打開或建立檔案。
#include <stdio.h>
FILE *fopen(const char *path, const char *mode);
參數 path: 參數 path 指向檔案路徑,可以是絕對路徑、也可以是相對路徑。
參數 mode: 參數 mode 指定了對該檔案的讀寫權限,是一個字元串。
mode | 說明 | 對應于 open()函數的 flags 參數取值 |
r | 以隻讀方式打開檔案 | O_RDONLY |
r+ | 以可讀、可寫方式打開檔案 | O_RDWR |
w | 以隻寫方式打開檔案,如果參數 path 指定的檔案存在,将檔案長度截斷為 0;如果指定檔案不存在則建立該檔案 | O_WRONLY | O_CREAT | O_TRUNC |
w+ | 以可讀、可寫方式打開檔案,如果參數 path 指定的檔案存在,将檔案長度截斷為 0;如果指定檔案不存在則建立該檔案。 | O_RDWR | O_CREAT | O_TRUNC |
a | 以隻寫方式打開檔案,打開以進行追加内容(在檔案末尾寫入),如果檔案不存在則建立該檔案。 | O_WRONLY | O_CREAT | O_APPEND |
a+ | 以可讀、可寫方式打開檔案,以追加方式寫入(在檔案末尾寫入),如果檔案不存在則建立該檔案。 | O_RDWR | O_CREAT | O_APPEND |
傳回值: 調用成功傳回一個指向 FILE 類型對象的指針(FILE *),該指針與打開或建立的檔案相關聯,後續的标準 I/O 操作将圍繞 FILE 指針進行。 如果失敗則傳回 NULL,并設定 errno 以訓示錯誤原因。
注:調用 fopen()函數建立檔案時無法手動指定檔案的權限,但卻有一個預設值:
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH (0666)
4、fclose()函數
關閉一個由 fopen()打開的檔案。
#include <stdio.h>
int fclose(FILE *stream);
參數 stream :為 FILE 類型指針,
傳回值 :調用成功傳回 0;失敗将傳回 EOF(也就是-1),并且會設定 errno 來訓示錯誤原因。
5、fread()函數
對檔案進行讀操作。
#include <stdio.h>
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
參數 ptr: 将讀取到的資料存放在參數 ptr 指向的緩沖區中;
參數 size:從檔案讀取 nmemb 個資料項,每一個資料項的大小為 size 個位元組,是以總共讀取的資料大小為 nmemb * size 個位元組。
參數 nmemb: 參數 nmemb 指定了讀取資料項的個數。
參數 stream: FILE 指針。
傳回值: 調用成功時傳回讀取到的資料項的數目;如果發生錯誤或到達檔案末尾,則 fread()傳回的值将小于參數 nmemb。
注:fread()傳回值不能區分檔案結尾和錯誤, 究竟是哪一種情況,此時可以使用 ferror()或 feof()函數來判斷。
6、fwrite()函數
對檔案進行寫操作。
#include <stdio.h>
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
參數 ptr: 将參數 ptr 指向的緩沖區中的資料寫入到檔案中。
參數 size: 參數 size 指定了每個資料項的位元組大小。
參數 nmemb: 參數 nmemb 指定了寫入的資料項個數。
參數 stream: FILE 指針。
傳回值: 調用成功時傳回讀取到的資料項的數目;如果發生錯誤,則 fwrite()傳回的值将小于參數 nmemb。
7、fseek()函數
設定檔案讀寫位置偏移量。
#include <stdio.h>
int fseek(FILE *stream, long offset, int whence);
參數 stream: FILE 指針。
參數 offset:偏移量,以位元組為機關。
參數 whence:
SEEK_SET | 讀寫偏移量将指向 offset 位元組位置處(從檔案頭部開始算) |
SEEK_CUR | 讀寫偏移量将指向目前位置偏移量 + offset 位元組位置處, offset 可以為正、也可以為負,如果是正數表示往後偏移,如果是負數則表示往前偏移 |
SEEK_END | 讀寫偏移量将指向檔案末尾 + offset 位元組位置處,同樣 offset 可以為正、也可以為負,如果是正數表示往後偏移、如果是負數則表示往前偏移。 |
傳回值: 成功傳回 0;發生錯誤将傳回-1,并且會設定 errno 以訓示錯誤原因;
注:傳回值成功傳回 0;發生錯誤将傳回-1!!!(與lseek的傳回值不一樣)。
8、ftell()函數
擷取檔案目前的讀寫位置偏移量。
#include <stdio.h>
long ftell(FILE *stream);
參數 stream: FILE 指針。
傳回值 偏移量。
注:可以通過 fseek()和 ftell()來計算出檔案的大小。
9、feof()函數
用于測試參數 stream 所指檔案的 end-of-file 标志。
#include <stdio.h>
int feof(FILE *stream);
參數 stream: FILE 指針。
傳回值 :如果 end-of-file 标志被設定了,則傳回一個非零值。如果 end-of-file 标志沒有被設定,則傳回 0。
10、ferror()函數
測試參數 stream 所指檔案的錯誤标志。
#include <stdio.h>
int ferror(FILE *stream);
參數 stream: FILE 指針。
傳回值 :如果錯誤标志被設定了,則調用 ferror()函數将傳回一個非零值,如果錯誤标志沒有被設定,則傳回 0。
11、clearerr()函數
清除 end-of-file 标志和錯誤标志,當調用 feof()或 ferror()校驗這些标志後,通常需要清除這些标志,避免下次校驗時使用到的是上一次設定的值,此時可以手動調用 clearerr()函數清除标志。
#include <stdio.h>
void clearerr(FILE *stream);
參數 stream: FILE 指針。
注:對于 end-of-file 标志,除了使用 clearerr()顯式清除之外,當調用 fseek()成功時也會清除檔案的 end-offile 标志。
12、stdio緩沖區
12.1、setvbuf()函數
對檔案的 stdio 緩沖區進行設定,譬如緩沖區的緩沖模式、 緩沖區的大小、起始位址等。
#include <stdio.h>
int setvbuf(FILE *stream, char *buf, int mode, size_t size);
參數 stream: FILE 指針,用于指定對應的檔案, 每一個檔案都可以設定它對應的 stdio 緩沖區。
參數 buf: 如果參數 buf 不為 NULL,那麼 buf 指向 size 大小的記憶體區域将作為該檔案的 stdio 緩沖區,因為stdio 庫會使用 buf 指向的緩沖區,是以應該以動态或靜态的方式在堆中為該緩沖區配置設定一塊空間,而不是配置設定在棧上的函數内的自動變量(局部變量)。如果 buf 等于 NULL,那麼 stdio 庫會自動配置設定一塊空間作為該檔案的 stdio 緩沖區(除非參數 mode 配置為非緩沖模式) 。
參數 mode: 參數 mode 用于指定緩沖區的緩沖類型,可取值如下:
_IONBF | 不對 I/O 進行緩沖(标準錯誤 stderr 預設屬于這一種類型,進而保證錯誤資訊能夠立即輸出) | 意味着每個标準 I/O 函數将立即調用 write()或者 read(),并且忽略 buf 和 size 參數(可以分别指定兩個參數為 NULL 和 0)。 |
_IOLBF | 采用行緩沖 I/O(對于終端裝置預設采用的就是行緩沖模式,譬如标準輸入和标準輸出) | 對于輸出流,在輸出一個換行符前将資料緩存(除非緩沖區已經被填滿), 當輸出換行符時,再将這一行資料通過檔案 I/O write()函數刷入到核心緩沖區中; 對于輸入流, 每次讀取一行資料。 |
_IOFBF | 采用全緩沖 I/O(預設普通磁盤上的正常檔案預設常用這種緩沖模式)。 | 對于輸出流,當 fwrite 寫入檔案的資料填滿緩沖區時,才調用 write()将 stdio 緩沖區中的資料刷入 核心緩沖區; 對于輸入流,每次讀取 stdio 緩沖區大小個位元組資料。 |
size: 指定緩沖區的大小。
傳回值: 成功傳回 0,失敗将傳回一個非 0 值,并且會設定 errno 來訓示錯誤原因。
12.2、setbuf()函數
setbuf()函數建構與 setvbuf()之上,執行類似的任務。要麼将 buf 設定為 NULL 以表示無緩沖,要麼指向由調用者配置設定的 BUFSIZ 個位元組大小的緩沖區(BUFSIZ 定義于頭檔案<stdio.h>中,該值通常為 8192)
#include <stdio.h>
void setbuf(FILE *stream, char *buf);
setbuf()調用除了不傳回函數結果(void)外,就相當于:
setvbuf(stream, buf, buf ? _IOFBF : _IONBF, BUFSIZ);
12.3、setbuffer()函數
對檔案的 stdio 緩沖區進行設定。
#include <stdio.h>
void setbuffer(FILE *stream, char *buf, size_t size);
setbuffer()調用除了不傳回函數結果(void)外,就相當于:
setvbuf(stream, buf, buf ? _IOFBF : _IONBF, size);
12.4、fflush()函數
重新整理stdio緩沖區。
#include <stdio.h>
int fflush(FILE *stream);
參數 stream:FILE指針對象。
傳回值:調用成功傳回 0,否則将傳回-1,并設定 errno 以訓示錯誤原因。
12.5、重新整理 stdio 緩沖區
1)調用 fflush()庫函數可強制重新整理指定檔案的 stdio 緩沖區;
2)調用 fclose()關閉檔案時會自動重新整理檔案的 stdio 緩沖區;
3)程式退出時會自動重新整理 stdio 緩沖區(注如果使用_exit 或_Exit()終止程式則不會重新整理) 。
13、檔案描述符與 FILE 指針互轉
13.1、fileno()函數
将标準 I/O 中使用的 FILE 指針轉換為檔案 I/O 中所使用的檔案描述符。
#include <stdio.h>
int fileno(FILE *stream);
參數 stream:要轉換的 FILE 指針
傳回值:成功傳回檔案描述符,錯誤将傳回-1,并且會設定 errno 來訓示錯誤原因。
13.2、fdopen()函數
将檔案 I/O 中所使用的檔案描述符轉換為标準 I/O 中使用的 FILE 指針。
#include <stdio.h>
FILE *fdopen(int fd, const char *mode);
參數 fd:要轉換的檔案描述符
參數 mode:同fopen的mode參數
傳回值:成功傳回FILE 指針,錯誤将傳回-1,并且會設定 errno 來訓示錯誤原因。