C5 標準IO庫:APUE 筆記

C5 :標準IO庫

   在第三章中,全部IO函數都是圍繞文件描述符展開,文件描述符用於後續IO操做。因爲文件描述符相關的操做是不帶緩衝的IO,須要操做者本人指定緩衝區分配、IO長度等,對設備環境要求必定的瞭解。數組

  本章引入文件流概念,IO庫將處理不少底層IO細節。安全

1 緩衝

  提供緩衝的目的是儘可能減小read和write的調用次數。標準IO提供瞭如下3種緩衝:函數

1.1 全緩衝

  在填滿標準IO緩衝區後再進行實際IO操做,標準IO函數一般使用malloc獲取使用的緩衝區spa

1.2 行緩衝

  在輸入和輸出中遇到換行符時,標準IO才執行IO操做。對於行緩衝有2個限制指針

  •   標準IO庫用來收集每一行的緩衝區長度固定,因此只要是填滿了緩衝區,就會進行IO操做
  •   只要是經過標準IO從一個不帶緩衝的流或者一個行緩衝的流獲得輸入數據,那麼就會flush行緩衝輸出流

1.3 不帶緩衝

  標準庫不對字符進行緩衝存儲,標準錯誤流一般是不帶緩衝的,這樣就能夠儘快將信息顯示出來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  不帶緩衝。對象

  •   若是指定一個不帶緩衝的流,則忽略buf和size參數。
  •   若是指定全緩衝和行緩衝,則buf和size可選擇指定一個緩衝區及其長度。
  •   若是流是帶緩衝的,而buf是NULL,則標準IO庫自動爲流分配合適長度的緩衝區,長度由BUFSIZE指定。

2 流

2.1 打開、關閉流

  可使用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.

 

2.2 讀、寫流

2.2.1 每次一個字符的IO

  下面函數用於一次讀取一個字符,頭文件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);

 

2.2.2 每次一行IO

  下面兩個函數每次讀寫輸出一行,頭文件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);

 

  注意如下兩點:

  •   應當屏蔽使用puts或者gets。這兩個函數都是從標準輸入或輸出讀寫,但因爲沒法指定緩衝區長度,將會致使緩衝區溢出錯誤
  •   程序退出處,顯示調用exit(0),將會沖洗任何未寫的數據,而後關閉全部打開的流
  •   讀寫一行都是以NULL爲終止,可是緩衝區的NULL不會寫入文件

3 二進制IO

  上一節的流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);

 

4 定位流(訪問偏移)

  可以使用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 格式化IO

5.1 格式化輸出

  格式化輸出由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的安全版本,指定了緩衝區的長度,防止緩衝區溢出

5.2 格式化輸入

  格式化輸入由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;

 6 臨時文件

  可使用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。

7 內存流

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;
相關文章
相關標籤/搜索