APUE學習筆記 第五章 標準I/O庫


第五章 標準I/O

1流和FILE對象

對於標準I/O庫,它們的操作是圍繞流進行的。流的定向決定了所讀、寫的字符是單字節還是多字節的。

#include <stdio.h>
#include <wchar.h>
int fwide(FILE *fp,int mode);
//返回值:若流是寬定向的,返回正值;若流是字節定向的,返回負值;若流是未定向的,返回0.

fwide函數可用於流的定向。根據mode參數的不同值,fwide函數執行不同的工作。

若mode參數值爲負,fwide將試圖使指定的流是字節定向的

若mode參數值爲正,fwide將試圖使指定的流是寬定向的

若mode參數值是0,fwide將不試圖設置流的定向,但返回標誌該流定向的值

當一個流最初被創建時,它並沒有定向。若在未定向的流上使用一個多字節(單字節)I/O函數,則將該流設置爲寬(字節)定向。fwide並不改變已定向流的定向。

 

2標準輸入、標準輸出和標準錯誤

對一個進程預定義了3個流:stdinstdoutstderr。這些流引用的文件與文件描述符STDIN_FILENOSTDOUT_FILENOSTDERR_FILENO所引用的相同。

 

3、緩衝

標準I/O庫提供緩衝的目的是儘可能減少使用read和write調用的次數,標準I/O提供了以下3種類型的緩衝:

a、全緩衝,在這種情況下,在填滿標準I/O緩衝區後才進行實際I/O操作。如磁盤上的文件通常實施全緩衝。

b、行緩衝,在這種情況下,當在輸入和輸出中遇到換行符,標準I/O執行I/O操作。如標準輸入輸出。

c、不帶緩衝,標準I/O庫不對字符進行緩衝存儲。標準錯誤流stderr通常是不帶緩衝的。

我們可以調用下面兩個函數更改緩衝類型

#include <stdio.h>
void setbuf(FILE *restrict fp,char *restrict buf);
int setvbuf(FILE *restrict fp,char *buf,int mode,size_t size);
//返回值:若成功,返回0;若出錯,返回非0.

可以使用setbuf打開或關閉緩衝機制,參數buf指定一個長度爲BUFSIZ的緩衝區。將buf設置爲NULL可以關閉緩衝。

使用setvbuf,我們可以精確地說明所需的緩衝類型。這是用mode參數實現的:

_IOFBF 全緩衝

_IOLBF 行緩衝

_IONBF 不帶緩衝

我們可以通過fflush函數沖洗一個流,此函數使該流所有未寫的數據都被傳送至內核。

#include <stdio.h>
int fflush(FILE *fp);
//返回值:若成功,返回0;若出錯,返回EOF。

 

4、打開流

下面3個函數打開一個標準I/O流

#include <stdio.h>
FILE *fopen(const char *restrict pathname,const char *restrict type);
FILE *freopen(const char *restrict pathname,const char *restrict type,FILE *restrict fp);
FILE *fdopen(int fd,const char *type);
//返回值:若成功,返回文件指針;若出錯,返回NULL。

    這三個函數的區別如下:

(1)、fopen函數打開路徑名爲pathname的一個指定的文件;

(2)、freopen函數在一個指定的流上打開一個指定的文件,如若該流已經打開,則先關閉該流。若該流已經定向,則使用freopen清除該定向。此函數一般用於將一個指定的文件打開爲一個預定義的流:標準輸入、標準輸出或標準錯誤。

(3)、fdopen函數取一個已有的文件描述符,並使一個標準的I/O流與該描述符相結合。此函數常用於由創建管道和網絡通信通道函數返回的描述符,因爲這些特殊類型的文件不能用標準I/O函數fopen打開。

type參數指定對該I/O流的讀、寫方式,ISO C規定type參數可以有如下15種不同的值:

其中b作爲type的一部分,這使得標準I/O系統可以區分文本文件和二進制文件。

調用fclose關閉一個打開的流

#include <stdio.h>
int fclose(FILE *fp);
//返回值:若成功,返回0;若出錯,返回EOF。

    在該文件被關閉之前,沖洗緩衝中的輸出數據。緩衝區中的任何輸入數據被丟棄。如果標準I/O庫已經爲該流自動分配了一個緩衝區,則釋放該緩衝區。當一個進程正常終止時,則所有帶未寫緩衝數據的標準I/O流都被沖洗,所有打開的標準I/O流都被關閉。

 

5、讀寫流

以下3個函數可用於一次讀一個字符

#include <stdio.h>
int getc(FILE *fp);
int fgetc(FILE *fp);
int getchar(void);   //等同於getc(stdin)
//返回值:若成功,返回下一個字符;若已到達文件尾端或出錯,返回EOF。

對應上面所述的每個輸入函數都有一個輸出函數

#include <stdio.h>
int putc(int c,FILE *fp);
int fputc(int c,FILE *fp);
int putchar(int c);
//返回值:若成功,返回c;若出錯,返回EOF。

    不管是出錯還是到達文件尾端,三個輸入函數都返回同樣的值,可以用下面的函數區分:

#include<stdio.h>
Int ferror(FILE *fp);
Int feof(FILE *fp);
兩個函數返回值:若條件爲真,返回非0,否則,返回0.
void clearerr(FILE *fp);

在大多數實現中,爲每個流在FILE對象中維護兩個標誌:出錯標誌和文件結束標誌調用clearerr可以清除這兩個標誌。

從流中讀取數據後,可以調用ungetc將字符再壓送回流中。

#include<stdio.h>
Int ungetc(int c,FILE *fp);
返回值:若成功,返回c;若出錯,返回EOF。

 

6、每次一行I/O

下面兩個函數提供每次輸入一行的功能

#include <stdio.h>
char *fgets(char *restrict buf,int n,FILE *restrict fp);  //buf爲緩衝區地址,讀入的行將送入其中,參數n指定緩衝的長度
char *gets(char *buf);  //從標準輸入讀,不推薦使用
//返回值:若成功,返回buf;若已到達文件尾端或出錯,返回NULL。

 fputs和puts提供每次輸出一行的功能

#include <stdio.h>
int fputs(const char *restrict str,FILE *restrict fp);
int puts(const char *str);
//返回值:若成功,返回非負值;若出錯,返回EOF。

函數fputs將一個以null字節終止的字符串寫到指定的流,而puts寫到標準輸出。

 

7二進制I/O

下列兩個函數執行二進制I/O操作

#include <stdio.h>
size_t fread(void *restrict ptr,size_t size,size_t nobj,FILE *restrict fp);
size_t fwrite(const void *restrict ptr,size_t size,size_t nobj,FILE *restrict fp);

參數size爲欲寫結構的長度,nobj爲欲寫的元素個數,函數返回的是讀或寫的對象數。這些函數有以下兩種常見的用法

//(1)、讀或寫一個二進制數組:
float data[10];
if(fwrite(&data[2],sizeof(float),4,fp)!=4)
    err_sys("fwrite error");
//(2)、讀寫一個結構
struct{
      short count;
      long total;
      char name[NAMESIZE];  
}item;

if(fwrite(&item,sizeof(item),1,fp)!=1)
     err_sys("fwrite error");

8、定位流

有3種方法定位標準I/O流

#include <stdio.h>
long ftell(FILE *fp);   
返回值:若成功,則返回當前文件位置指示,出錯則返回-lL
int fseek(FILE *fp,long offset,int whence);
返回值:若成功,返回0;若出錯,返回-1;
void rewind(FILE *fp);

除了偏移量的類型是off_t而非long以外,ftello函數與ftell相同,fseeko函數與fseek相同

#include <stdio.h>
off_t ftello(FILE *fp);
int fseeko(FILE *fp,off_t offset,int whence);

下面函數是ISO C標準引入的

#include <stdio.h>
int fgetpos(FILE *restrict fp,fpos_t *restrict pos);
int fsetpos(FILE *fp,const fpos_t *pos);
返回值:若成功,返回0;若出錯,返回非0.

    fgetpos將文件位置指示器的當前值存入由pos指向的對象中,在以後調用fsetpos時,可以使用此值將流重新定位至該位置。

 

9、格式化I/O

    格式化輸出是由printf函數處理的

#include <stdio.h>
int printf(const char *restrict format,...);
int fprintf(FILE *restrict fp,const char *restrict format,...);
int dprintf(int fd,const char *restrict format,...);
  //三個函數返回值:若成功,返回輸出字節數;若出錯,返回負值
int sprintf(char *restrict buf,const char *restrict format,...);
  //返回值:若成功,返回存入數組的字符數;若出錯,返回負值。
int snprintf(char *restrict buf,size_t n,const char *restrict format,...);    //參數n指定緩衝區長度
  //返回值:若緩衝區足夠大,返回將要存入數組的字符數;若出錯,返回負值。

執行格式化輸入處理的是3個scanf函數

#include <stdio.h>
int scanf(const char *restrict format,...);
int fscanf(FILE *restrict fp,const char *restrict format,...);
int sscanf(const char *restrict buf,const char *restrict format,...);
  //三個函數返回值:賦值的輸入項數;若輸入出錯或在任一轉換前已到達文件文件尾端,返回EOF。

 

10、臨時文件

ISO C標準I/O庫提供了兩個函數以幫助創建臨時文件

#include <stdio.h>
char *tmpnam(char *ptr);
  //返回值:指向唯一路徑名的指針。
FILE *tmpfile(void);
  //返回值:若成功,返回文件指針;若出錯,返回NULL。

tmpnam函數產生一個與現有文件名不同的一個有效路徑名字符串,tmpfile創建一個臨時二進制文件(類型wb+),在關閉該文件或程序結束時將自動刪除。

 

參考:http://www.cnblogs.com/runnyu/p/4635382.html

發佈了33 篇原創文章 · 獲贊 8 · 訪問量 8186
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章