標準I/O庫處理不少細節,如緩衝區分配、以優化的塊長度執行I/O等。這些處理使用戶沒必要擔憂如何選擇正確的塊長度。數組
標準I/O庫提供緩衝的目的是儘量減小使用read和write的調用次數。標準I/O提供了3種類型的緩衝。安全
對於任何一個給定的流,若是咱們不喜歡這些系統默認,則可調用下列兩個函數中的一個更改緩衝類型。網絡
#include <stdio.h> void setbuf(FILE *fp, char *buf); int setvbuf(FILE *fp, char *buf, int mode, size_t size); 返回值:若成功,返回0;若出錯,返回非0
可使用setbuf函數打開或關閉緩衝機制。爲了帶緩衝I/O,參數buf必須指向一個長度爲BUFSIZ的緩衝區(該常量定義在<stdio.h>中)。一般在此以後該流就是全緩衝的。爲了關閉緩衝,將buf設置爲NULL。函數
使用setvbuf函數,能夠精確的說明所需的緩衝類型。這是用mode參數實現的:優化
若是指定一個不帶緩衝的流,則忽略buf和size參數。若是指定全緩衝或行緩衝,則buf和size可選擇地指定一個緩衝區及其長度。若是該流是帶緩衝的,而buf是NULL,則標準I/O庫將自動地爲該流分配適當長度的緩衝區。適當長度指的是由常量BUFSIZ所指定的值。spa
通常而言,應由系統選擇緩衝區的長度,並自動分配緩衝區。指針
任什麼時候候,咱們均可以用fflush函數沖洗一個流。code
#include <stdio.h> int fflush(FILE *fp); 返回值:若成功,返回0;若出錯,返回EOF
#include <stdio.h> FILE *fopen(const char *pathname, const char *type); FILE *freopen(const char *pathname, const char *type, FILE *fp); FILE *fdopen(int fd, const char *type); 3個函數返回值:若成功,返回文件指針;若出錯,返回NULL
這三個函數的區別以下。orm
參數type指定對該I/O流的讀寫方式。對象
type | 說明 | open(2)標誌 |
---|---|---|
r或rb | 爲讀而打開 | O_RDONLY |
w或wb | 把文件截斷至0,或爲寫而建立 | O_WRONLY | O_CREAT | O_TRUNC |
a或ab | 追加;爲在文件尾寫而打開,或爲寫而建立 | O_WRONLY | O_CREAT | O_APPEND |
r+或r+b或rb+ | 爲讀和寫而打開 | O_RDWR |
w+或w+b或wb+ | 把文件截斷至0長,或爲讀和寫而打開 | O_RDWR | O_CREAT | O_TRUNC |
a+或a+b或ab+ | 爲在文件尾讀和寫而打開或建立 | O_RDWR | O_CREAT | O_APPEND |
除非流引用了終端設備,不然按系統默認,流被打開時是全緩衝的。若流引用終端設備,則該流是行緩衝的。
調用fclose關閉一個打開的流。
#include <stdio.h> int fclose(FILE *fp); 返回值:若成功,返回0;若出錯,返回EOF
在該文件被關閉以前,沖洗緩衝中的輸出數據。當一個進程正常終止時,則全部帶未寫緩衝數據的標準I/O流都被沖洗,全部打開的標準I/O流都被關閉。
一旦打開了流,則可在三種不一樣類型的非格式化I/O中進行選擇,對其進行讀寫操做。
#include <stdio.h> int getc(FILE *fp); int fgetc(FILE *fp); int getchar(void); 三個函數的返回值:若成功,返回下一個字符;若已到達文件尾或出錯,返回EOF
前兩個函數的區別是,getc可被實現爲宏,而fgetc不能實現爲宏。這意味着如下幾點。
注意,不論是到達文件尾仍是出錯,這三個函數都返回相同的值。爲了區分不一樣的狀況,必須調用ferror或feof。
#include <stdio.h> int ferror(FILE *fp); int feof(FILE *fp); 兩個函數返回值:若條件爲真,返回非0;不然,返回0 void clearerr(FILE *fp);
大多數實現中,爲每一個流在FILE對象中維護了兩個標誌:出錯標誌;文件結束標誌。調用clearerr能夠清除這兩個標誌。
對應於getc,fgetc和getchar三個輸入函數,輸出函數以下。
#include <stdio.h> int putc(int c, FILE *fp); int fputc(int c, FILE *fp); int putchar(int c); 三個函數返回值:若成功,返回c;若出錯,返回EOF
如下兩個函數提供每次輸入一行的功能。
#include <stdio.h> char *fgets(char *buf, int n, FILE *fp); char *gets(char *buf); 兩個函數返回值:若成功,返回buf;若已到達文件尾或出錯,返回NULL
gets從標準輸入讀,而fgets從指定的流讀。對於fgets,必須指定緩衝的長度n,此函數一直讀到寫一個換行符爲止,可是不超過n-1個字符,讀入的字符被送入緩衝區。該緩衝區以null字符結尾。若是改行包括最後一個換行符的字符數超過n-1,則fgets只返回一個不完整的行,可是,緩衝區老是以null字符結尾。對fgets的下一次調用會繼續讀該行。gets是一個不推薦使用的函數。其問題是調用者在使用gets時不能指定緩衝區的長度。這有可能致使內存溢出,產生不可預料的結果。
fputs和puts提供每次輸出一行的功能。
#include <stdio.h> int fputs(const char *str, FILE *fp); int puts(const char *str); 兩個函數返回值:若成功,返回非負值;若出錯,返回EOF
函數fputs將一個以null字符終止的字符串寫到指定的流,尾端的null字符不寫出。puts將一個以null字符終止的字符串寫到標準輸出,null字符不寫出。可是,puts隨後又將一個換行符寫到標準輸出。
#include <stdio.h> size_t fread(void *ptr, size_t size, size_t nobj, FILE *fp); size_t fwrite(const void *ptr, size_t size, size_t nobj, FILE *fp); 兩個函數返回值:讀或寫的對象數
fread和fwrite返回讀或寫的對象數。對於讀,若是出錯或到達文件尾端,則此數字能夠少於nobj。在這種狀況應該用ferror或feof以判斷到底是哪種狀況。對於寫,若是返回值少於nobj,則出錯。
有三種方式能夠定位標準I/O流。
#include <stdio.h> long ftell(FILE *fp); 返回值:若成功,返回當前文件位置指示;若出錯,返回-1L int fseek(FILE *fp, long offset, int whence); 返回值:若成功,返回0;若出錯,返回-1 void rewind(FILE *fp);
使用rewind函數也能夠將一個流設置到文件的起始位置。
除了偏移量的類型是off_t之外,ftello函數與ftell相同,fseeko與fseek相同。
#include <stdio.h> off_t ftello(FILE *fp); 返回值:若成功,返回當前文件位置;若出錯,返回(off_t)-1 int fseeko(FILE *fp, off_t offset, int whence); 返回值:若成功,返回0;若出錯,返回-1
#include <stdio.h> int fgetpos(FILE *fp, fpos_t *pos); int fsetpos(FILE *fp, const fpos_t *pos); 兩個函數返回值:若成功,返回0;若出錯,返回-1
fgetpos將文件位置指示器的當前值存入pos指向的對象中。在之後調用fsetpos時,可使用此值將流從新定位至該位置。
5個格式化輸出函數。
#include <stdio.h> int printf(const char *format, ...); int fprintf(FILE *fp, const char *format, ...); int dprintf(int fd, const char *format, ...); 三個函數返回值:若成功,返回輸出字符數;若輸出錯誤,返回負值 int sprintf(char *buf, const char *format, ...); 返回值:若成功,返回存入數組的字符數;若出錯,返回負值 int snprintf(char *buf, size_t n, const char *format, ...); 返回值:若緩衝區足夠大,返回將要存入數組的字符數;若出錯,返回負值
printf將格式化數據寫到標準輸出,fprintf寫到指定的流,dprintf寫到指定的文件描述符,sprintf將格式化數據寫入buf中,sprintf自動在buf尾端添加null字符,但null字符不包含在返回值中。snprintf指定了緩衝區的長度,若是輸入的字符數超過緩衝區長度,則將被丟棄。使用snprintf更加安全。
5個格式化輸出函數的變體,將可變參數換成了arg。
#include <stdarg.h> #include <stdio.h> int vprintf(const char *format, va_list arg); int vfprintf(FILE *fp, const char *format, va_list arg); int vdprintf(int fd, const char *format, va_list arg); 3個函數的返回值:若成功,返回輸出的字符數;若出錯,返回負值 int vsprintf(char *buf, const char *format, va_list arg); 返回值:若成功,返回存入數組的字符數;若出錯,返回負值 int vsnprintf(char *buf, size_t n, const char *format, va_list arg); 返回值:若緩衝區足夠大,返回存入數組的字符數;若出錯,返回負值
一個轉換說明有4個可選的部分。
%[flags][fieldwidth][precision][lenmodifier]convtype
標誌 | 說明 |
---|---|
' | 將整數按千位分組字符 |
- | 在字段內左對齊輸出 |
+ | 老是顯示帶符號轉換的正負號 |
space | 若是第一個字符不是正負號,則在其前面加上空格 |
# | 指定另外一種轉換形式(例如,對於十六進制格式,加0x前綴) |
0 | 添加前導0(而非空格)進行填充 |
對於轉換說明請參考APUE的第128頁到129頁的詳細說明。
#include <stdio.h> int scanf(const char *format, ...); int fscanf(FILE *fp, const char *format, ...); int sscanf(const char *buf, const char *format, ...); 三個函數的返回值:賦值的輸入項數;若輸入出錯或在任一轉換前已經到達文件尾端,返回EOF
#include <stdarg.h> #include <stdio.h> int vscanf(const char *format, va_list arg); int vfscanf(FILE *fp, const char *format, va_list arg); int vsscanf(const char *buf, const char *format, va_list arg); 三個函數返回值:指定的輸入項目數;若出錯或在任一轉換前文件結束,返回EOF
可使用fileno函數獲取流的文件描述符。
#include <stdio.h> int fileno(FILE *fp); 返回值:與該流相關的文件描述符
ISO C標準庫提供了兩個函數以幫助建立臨時文件。
#include <stdio.h> char *tmpnam(char *ptr); 返回值:指向惟一路徑名的指針 FILE *tmpfile(void); 返回值:若成功,返回文件指針;若出錯,返回NULL
tmpnam產生一個與現有文件名不一樣的有效路徑名字符串。tmpfile建立一個臨時二進制文件(wb+),在關閉該文件或程序結束時將自動刪除該文件。
Single UNIX Specification爲處理臨時文件定義了另外兩個函數。
#include <stdlib.h> char *mkdtemp(char *template); 返回值:若成功,返回指向目錄名的指針;若出錯,返回NULL int mkstemp(char *template); 返回值:若成功,返回文件描述符;若出錯,返回-1
有3個函數能夠用於內存流的建立。
#include <stdio.h> FILE *fmemopen(void *buf, size_t size, const char *type); 返回值:若成功,返回流指針;若錯誤,返回NULL