在第三章中,全部IO函數都是圍繞文件描述符展開,文件描述符用於後續IO操做。因爲文件描述符相關的操做是不帶緩衝的IO,須要操做者本人指定緩衝區分配、IO長度等,對設備環境要求必定的瞭解。數組
本章引入文件流概念,IO庫將處理不少底層IO細節。安全
提供緩衝的目的是儘可能減小read和write的調用次數。標準IO提供瞭如下3種緩衝:函數
在填滿標準IO緩衝區後再進行實際IO操做,標準IO函數一般使用malloc獲取使用的緩衝區spa
在輸入和輸出中遇到換行符時,標準IO才執行IO操做。對於行緩衝有2個限制指針
標準庫不對字符進行緩衝存儲,標準錯誤流一般是不帶緩衝的,這樣就能夠儘快將信息顯示出來rest
可使用setbuf函數打開或者關閉緩衝機制,爲了帶緩衝進行IO,參數buf必須指向一個長度爲BUFSIZE的緩衝區,頭文件stdio.h。成功返回-,出錯返回-1。code
1 /* If BUF is NULL, make STREAM unbuffered. 2 Else make it use buffer BUF, of size BUFSIZ. */ 3 extern void setbuf (FILE *__restrict __stream, char *__restrict __buf) __THROW; 4 5 /* Make STREAM use buffering mode MODE. 6 If BUF is not NULL, use N bytes of it for buffering; 7 else allocate an internal buffer N bytes long. */ 8 extern int setvbuf (FILE *__restrict __stream, char *__restrict __buf, int __modes, size_t __n) __THROW;
setvbuf的mode參數能夠精確說明緩衝類型,mode參數實現爲:orm
_IOFBF 全緩衝,_IOLBF 行緩衝,_IONBF 不帶緩衝。對象
可使用fopen等函數打開一個IO流,頭文件stdio.h。成功返回文件指針,出錯返回NULL。blog
1 /* Open a file and create a new stream for it. 2 3 This function is a possible cancellation point and therefore not 4 marked with __THROW. */ 5 extern FILE *fopen (const char *__restrict __filename, 6 const char *__restrict __modes) __wur; 7 /* Open a file, replacing an existing stream with it. 8 9 This function is a possible cancellation point and therefore not 10 marked with __THROW. */ 11 extern FILE *freopen (const char *__restrict __filename, 12 const char *__restrict __modes, 13 FILE *__restrict __stream) __wur;
fopen函數打開路徑爲__filename的文件
freopen函數在一個指定的流上打開文件。若是該流已經打開,則先關閉該流。若是該流已經定向,則使用freopen清除該定向。
mode參數指定對該IO流的讀寫方式,ISO C規定mode參數能夠右15種取值。
使用fclose能夠關閉一個打開的流,頭文件stdio.h。成功返回0,失敗返回-1。
1 /* Close STREAM. 2 3 This function is a possible cancellation point and therefore not 4 marked with __THROW. */ 5 extern int fclose (FILE *__stream); 6 /* Flush STREAM, or all streams if STREAM is NULL.
下面函數用於一次讀取一個字符,頭文件stdio.h。成功返回下一個字符,達到文件尾或者出錯,返回EOF(定義在libio.h)。
1 /* Read a character from STREAM. 2 3 These functions are possible cancellation points and therefore not 4 marked with __THROW. */ 5 extern int fgetc (FILE *__stream); 6 extern int getc (FILE *__stream); 7 8 /* Read a character from stdin. 9 10 This function is a possible cancellation point and therefore not 11 marked with __THROW. */ 12 extern int getchar (void); 13 14 #ifndef EOF 15 # define EOF (-1) 16 #endif
前兩個函數的區別是,getc能夠被實現爲宏,而fgetc不能實現爲宏?
getchar等價於geic (stdin)。
這三個函數達到文件尾或者出錯,都返回EOF。爲區別文件尾或者出錯,須要調用如下函數進行判斷,頭文件stdio.h。成功返回非0,失敗返回0。能夠做爲bool型判斷。
1 /* Clear the error and EOF indicators for STREAM. */ 2 extern void clearerr (FILE *__stream) __THROW; 3 /* Return the EOF indicator for STREAM. */ 4 extern int feof (FILE *__stream) __THROW __wur; 5 /* Return the error indicator for STREAM. */ 6 extern int ferror (FILE *__stream) __THROW __wur;
調用clearerr能夠清除這兩個標誌。
也可使用ubgetc將字符再寫回流緩衝區,頭文件stdio.h。成功返回c,失敗返回EOF。
1 /* Push a character back onto the input buffer of STREAM. 2 3 This function is a possible cancellation point and therefore not 4 marked with __THROW. */ 5 extern int ungetc (int __c, FILE *__stream);
對應的寫緩衝區函數爲:
1 /* Write a character to STREAM. 2 3 These functions are possible cancellation points and therefore not 4 marked with __THROW. 5 6 These functions is a possible cancellation point and therefore not 7 marked with __THROW. */ 8 extern int fputc (int __c, FILE *__stream); 9 extern int putc (int __c, FILE *__stream); 10 11 /* Write a character to stdout. 12 13 This function is a possible cancellation point and therefore not 14 marked with __THROW. */ 15 extern int putchar (int __c);
下面兩個函數每次讀寫輸出一行,頭文件stdio.h。成功返回buf,到達文件尾或者出錯,返回NULL。
1 /* Get a newline-terminated string of finite length from STREAM. 2 3 This function is a possible cancellation point and therefore not 4 marked with __THROW. */ 5 extern char *fgets (char *__restrict __s, int __n, FILE *__restrict __stream) 6 __wur; 7 8 /* Get a newline-terminated string from stdin, removing the newline. 9 10 This function is impossible to use safely. It has been officially 11 removed from ISO C11 and ISO C++14, and we have also removed it 12 from the _GNU_SOURCE feature list. It remains available when 13 explicitly using an old ISO C, Unix, or POSIX standard. 14 15 This function is a possible cancellation point and therefore not 16 marked with __THROW. */ 17 extern char *gets (char *__s) __wur __attribute_deprecated__; 18 19 20 /* Write a string to STREAM. 21 22 This function is a possible cancellation point and therefore not 23 marked with __THROW. */ 24 extern int fputs (const char *__restrict __s, FILE *__restrict __stream); 25 26 /* Write a string, followed by a newline, to stdout. 27 28 This function is a possible cancellation point and therefore not 29 marked with __THROW. */ 30 extern int puts (const char *__s);
注意如下兩點:
上一節的流IO沒法解決如下問題:當讀取的數據是結構化數據(非字符串,可能讀取到NULL,0),流IO將會截斷。
爲解決該問題,須要引入二進制IO函數fread和fwrite,頭文件stdio.h。函數返回讀或寫的對象數。
1 /* Read chunks of generic data from STREAM. 2 3 This function is a possible cancellation point and therefore not 4 marked with __THROW. */ 5 extern size_t fread (void *__restrict __ptr, size_t __size, 6 size_t __n, FILE *__restrict __stream) __wur; 7 /* Write chunks of generic data to STREAM. 8 9 This function is a possible cancellation point and therefore not 10 marked with __THROW. */ 11 extern size_t fwrite (const void *__restrict __ptr, size_t __size, 12 size_t __n, FILE *__restrict __s);
可以使用ftell獲取當前文件訪問偏移量、fseek對文件訪問進行偏移、rewind將流設置到起始位置。
1 /* Seek to a certain position on STREAM. 2 3 This function is a possible cancellation point and therefore not 4 marked with __THROW. */ 5 extern int fseek (FILE *__stream, long int __off, int __whence); 6 /* Return the current position of STREAM. 7 8 This function is a possible cancellation point and therefore not 9 marked with __THROW. */ 10 extern long int ftell (FILE *__stream) __wur; 11 /* Rewind to the beginning of STREAM. 12 13 This function is a possible cancellation point and therefore not 14 marked with __THROW. */ 15 extern void rewind (FILE *__stream);
fseek的第三個參數whence與fseek的參數相同:
SEEK_SET指定從文件起始位置開始,SEEK_CUR指定從當前位置開始,SEEK_END指定從文件末尾
格式化輸出由5個printf函數處理,頭文件stdio.h。成功返回字符數,失敗返回負值。
1 /* Write formatted output to stdout. 2 3 This function is a possible cancellation point and therefore not 4 marked with __THROW. */ 5 extern int printf (const char *__restrict __format, ...); 6 7 /* Write formatted output to STREAM. 8 9 This function is a possible cancellation point and therefore not 10 marked with __THROW. */ 11 extern int fprintf (FILE *__restrict __stream, 12 const char *__restrict __format, ...); 13 14 extern int dprintf (int __fd, const char *__restrict __fmt, ...) 15 __attribute__ ((__format__ (__printf__, 2, 3))); 16 17 /* Write formatted output to S. */ 18 extern int sprintf (char *__restrict __s, 19 const char *__restrict __format, ...) __THROWNL; 20 21 /* Maximum chars of output to write in MAXLEN. */ 22 extern int snprintf (char *__restrict __s, size_t __maxlen, 23 const char *__restrict __format, ...) 24 __THROWNL __attribute__ ((__format__ (__printf__, 3, 4)));
printf將格式化數據寫到標準輸出
fprintf將格式化數據寫到指定的流
dprintf寫到指定的文件描述符
sprintf寫到數組S
snprintf是sprintf的安全版本,指定了緩衝區的長度,防止緩衝區溢出
格式化輸入由3個scanf函數處理,頭文件stdio.h。成功返回輸入的參數,失敗或者到達文件末尾,返回EOF。
1 /* Read formatted input from STREAM. 2 3 This function is a possible cancellation point and therefore not 4 marked with __THROW. */ 5 extern int fscanf (FILE *__restrict __stream, 6 const char *__restrict __format, ...) __wur; 7 /* Read formatted input from stdin. 8 9 This function is a possible cancellation point and therefore not 10 marked with __THROW. */ 11 extern int scanf (const char *__restrict __format, ...) __wur; 12 /* Read formatted input from S. */ 13 extern int sscanf (const char *__restrict __s, 14 const char *__restrict __format, ...) __THROW;
可使用tmpnam或者tmpfile建立臨時二進制文件。頭文件stdio.h。
1 /* Generate a temporary filename. */ 2 extern char *tmpnam (char *__s) __THROW __wur; 3 4 /* Create a temporary file and open it read/write. 5 6 This function is a possible cancellation point and therefore not 7 marked with __THROW. */ 8 extern FILE *tmpfile (void) __wur;
tmpnam生成一個和現有文件名不一樣的有效路徑字符串,最多調用TMP_MAX次,定義在stdio.h。返回指向惟一路徑名的指針。若是輸入爲NULL,則路徑名存放在靜態區;若是不是NULL,則應該指向長度爲L_tmpnam個字符的數組。
tmpfile建立一個臨時二進制文件,在關閉該文件或者程序結束時將自動刪除該文件。可使用tmpfile建立一個臨時文件,而後當即unlink。
1 /* Create a new stream that refers to a memory buffer. */ 2 extern FILE *fmemopen (void *__s, size_t __len, const char *__modes) 3 __THROW __wur; 4 5 /* Open a stream that writes into a malloc'd buffer that is expanded as 6 necessary. *BUFLOC and *SIZELOC are updated with the buffer's location 7 and the number of characters written on fflush or fclose. */ 8 extern FILE *open_memstream (char **__bufloc, size_t *__sizeloc) __THROW __wur;