標準IO

一、關於標準IO緩衝區

標準IO提供緩衝的目的是儘可能減少使用read和write調用的此數,他對每個IO流自動地進行緩衝管理。標準IO提供三種類型的緩衝:
1、全緩衝:這種情況下,當標準IO緩衝區填滿後才進行實際IO操作。在一個流上執行第一次IO時,相關標準IO函數通常調用malloc獲得所需的緩衝區。全緩衝的緩衝區大小一般爲8192(具體要看設置)
2、行緩衝:當輸入和輸出中遇到換行符‘\n’時,纔會執行實際IO操作。當涉及一個終端時(例如標準輸入和標準出錯),通常使用行緩衝。
因爲標準IO庫用來收集每一行的緩衝區的長度是固定的,所以只要行緩衝區滿了,即使還沒有寫一個換行符,也會進行IO操作
3、不帶緩衝:標準IO庫不對字符進行緩衝存儲,只要執行了輸入和輸出操作,便會立即實行IO操作。標準出錯stderr通常是不帶緩衝的。

對於進程預定義了三個流,並且這三個流可以自動地被進程使用:
標準輸入:stdin
標準輸出:stdout
標準出錯:stderr

ISO  C要求下列緩衝特徵:
當且僅當標準輸入和標準輸出並不涉及交互式設備時,它們纔是全緩衝。否則一般爲行緩衝。
人機交互要求不可全緩衝。
標準出錯絕不會是全緩衝的
涉及終端設備的其他流,一般爲行緩衝的,否則是全緩衝。
普通文件一般爲全緩衝


可以使用下面兩個函數更改緩衝類型:

void setbuf(FILE *stream, char *buf);
功能:更改流的緩衝類型
參數:
          stream:要更改緩衝類型的流指針
          buf:緩衝區的長度,通常指定爲BUFSIZ,通常在此之後流就是全緩衝的。如果爲NULL,則關閉緩衝。
返回值:成功返回0,錯誤返回非0值

int setvbuf(FILE *stream, char *buf, int mode, size_t size);
功能:更改流的緩衝類型
參數:
            stream:要更改緩衝類型的流指針
             buf:如果被設置爲不帶緩衝的流,則忽略buf和size,如果指定了全緩衝或行緩衝,buf指定了緩衝區的地址,size指定了緩衝區的長度。如果buf爲NULL,系統自動分配全緩衝區或行緩衝區合適的長度。
             mode:
                           指定所需的緩衝類型    
                            _IOFBF         全緩衝
                            _IOLBF          行緩衝
                            _IONBU        不帶緩衝
             size:緩衝區大小
返回值: 成功返回0,錯誤返回非0值

int fflush(FILE *stream);
功能:沖洗一個流,此函數使該流所有未寫的數據都被傳送至內核
參數:
        stream:要衝洗的流,如果爲NULL,則沖洗所有輸出流
返回值:成功返回0,失敗返回EOF

沖洗說明標準IO緩衝區的寫操作,flush有兩種意思,在標準IO庫方面,flush意味着將緩衝區的內容寫到磁盤上。在終端驅動程序方面,flush表示丟棄已存儲在緩衝區的數據


二、流的定向
對於ASCII字符集,一個字符用一個字節表示,對於國際字符集,一個字符可用多個字節表示。標準IO文件流可用於單字節或多字節(寬)字符集。流的定向決定了所讀寫的字符是單字節還是多字節。當一個流最初被創建時,它並沒有定向。如若在未定向的流上使用一個多字節IO函數,則將該流的定向設置爲寬定向。如若在未定向的流上使用一個單字節IO函數,則將該流的定向設置爲字節定向。
可用以下函數設置流的定向:

int fwide(FILE *stream, int mode);
功能:設置一個未定向流的定向
參數:
                    stream:要改變定向的流
mode:
爲負值時,試圖將指定的流設置爲字節定向
爲正值時,試圖將指定的流設置爲寬定向
爲0時,不設置流的定向,但返回標示該流定向的值
返回值:若流是寬定向的則返回正值,若流是字節定向的則返回負值,若流是未定向的,則返回0。無出錯返回
注:fwaid只能改變未定向的流。並不改變已定向的流


三、標準IO的一些函數
FILE *fopen(const char *path, const char *mode);
功能:打開一個指定文件,返回一個標準IO流
參數:
        path:文件所在路徑
        mode:打開方式
                    r:只讀方式打開,打開後從文件頭開始讀
                    r+:讀寫方式打開,打開後從文件頭開始讀寫
                    w:只寫方式打開,文件不存在則創建,存在則把文件截短至0,即將文件清空
                    w+:讀寫方式打開,文件不存在則創建,存在則把文件截短至0,即將文件清空
                    a:只寫打開,文件不存在則創建,存在以只寫方式追加,即從文件尾部開始寫
                    a+:讀寫方式打開,文件不存在則創建,存在則讀文件時從文件頭開始,寫文件時從文件尾開始
當指定參數b時,表示以二進制方式打開,不過因爲UNIX不對文本文件和二進制文件進行區分,所以在UNIX環境下指定b實際上並無作用
返回值:成功返回流指針,失敗返回NULL

FILE *freopen(const char *path, const char *mode, FILE *stream);
功能:在一個指定的流上打開一個指定的文件,如若該流已經打開,則先關閉該流。若該流已經定向,則freopen清除該定向。此函數一般用於將一個指定的文件打開爲一個預訂義的流:標準輸入,標準輸出或標準出錯。
參數:
                 path:文件所在路徑
                 mode:  
                    r:只讀方式打開,打開後從文件頭開始讀
                    r+:讀寫方式打開,打開後從文件頭開始讀寫
                    w:只寫方式打開,文件不存在則創建,存在則把文件截短至0,即將文件清空
                    w+:讀寫方式打開,文件不存在則創建,存在則把文件截短至0,即將文件清空
                    a:只寫打開,文件不存在則創建,存在以只寫方式追加,即從文件尾部開始寫
                    a+:讀寫方式打開,文件不存在則創建,存在則讀文件時從文件頭開始,寫文件時從文件尾開始
當指定參數b時,表示以二進制方式打開,不過因爲UNIX不對文本文件和二進制文件進行區分,所以在UNIX環境下指定b實際上並無作用

                  stream:要在此流上打開文件
返回值:成功返回流指針,失敗返回NULL

FILE *fdopen(int fd, const char *mode);
功能:將一個現有的文件描述符和一個標準IO流相結合
參數:
         fd:一個已經打開的文件描述符
         mode:
                    和fopen一樣,不過此函數爲寫打開時,並不將文件清空。另外追加方式也不能創建該文件(因爲文件已經存在)
        
返回值:成功返回生成的流指針,失敗返回NULL
注:此文件描述符必須是一個已經打開的文件描述符


四、標準IO讀寫

int fgetc(FILE *stream);
功能:從指定的流中丟讀取字符
參數:stream:要讀取的流
返回值:成功返回字符,失敗或讀到文件尾部返回EOF(-1)


int fputc(int c, FILE *stream);
功能:向指定的流中寫一個字符
參數:
c:要寫入的字符
stream:要寫入的流
返回值:成功返回寫的字符,錯誤返回EOF


char *fgets(char *s, int size, FILE *stream);
功能:從指定的流讀取多個字符存放在s指向的地址,每次讀一行,以一個換行符終止
參數:
            s:將讀取到的數據存放到s中
            size:緩衝區長度
            stream:要讀取的文件流
返回值:成功返回s,失敗或讀到結尾返回NULL
注:
  • 每次fgets最多隻能讀取size-1個字符,因爲每次讀取結束時都會自動加‘\0’
  • 如果讀取過程中遇到‘\n’,則讀取結束,'\n'會被讀走


int fputs(const char *s, FILE *stream);
功能:將字符串寫到指定的流
參數:
          s:s中存放將要寫入的數據
          stream:要寫的文件流
返回值:成功返回寫入的字符個數,失敗返回EOF
注:如果遇到‘\n’則結束寫


size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
功能:從指定的流讀取多數據存放在ptr指向的地址
參數:
          ptr:將已讀取的數據存放到ptr中
          size:要讀取對象的大小
          nmemb:要求讀取對象的個數
          stream:要讀取的流
返回值:返回實際讀取的對象的個數


size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);
功能:將數據寫向指定的流
參數:
          ptr:存放要寫入的數據存放在ptr中
          size:要寫入數據的對象的大小
          nmemb:要求寫入數據的對象的個數
          stream:要寫入的流
返回值:返回實際寫入的對象的個數,如果返回值小於所要求的nmemb,則出錯

注:

1、在上面的三個讀操作中,不區分出錯和到達文件尾,爲了區分這兩種情況,需調用以下兩個函數
int feof(FILE *stream);
int ferror(FILE *stream);
兩個函數的返回值:若條件爲真則返回非0值。否則返回0

2、在大多數實現中,爲每個流在FILE對象中維持了兩個標誌:
  • 出錯標誌
  • 文件結束標誌 
     調用clearerr清除這兩個標誌 
    void clearerr(FILE *stream);

3、從流中讀取數據以後可以調用ungetc將字符再壓送回流中
        int ungetc(int c, FILE *stream);
         參數:c:要回送的字符
                    stream:要回送的流
         返回值:成功返回c,出錯返回eof
        
        壓送回流中的字符以後又可從流中讀出。ISO C允許實現支持任何次數的回送,但是它要求時限提供一次只送回一個字符,我們不能期望一次能送回多個字符
        回送的字符不必一定是上一次讀到的字符,參數c既可以是上次讀出的字符,也可以是任意別的字符,但不能回送EOF。但是當已經到達文件尾端時,仍可以回送一個字符,下次讀將返回該字符,再次讀則返回EOF。之所以能這樣做的原因是一次成功的ungetc調用會清除該流的文件結束標誌。



五、文件定位

int fseeko(FILE *stream, off_t offset, int whence);
int fseek(FILE *stream, long offset, int whence);
功能:更改內核中offset的值
參數:
            stream:要更改的文件流
            offset:偏移值。offset>0,向後偏移,offset<0,向前偏移。
            whence:
                    SEEK_SET  從文件其實位置開始
                    SEEK_CUR 從文件當前位置開始
                    SEEK_END 從文件尾端開始
返回值:成功返回0,失敗返回-1
注:上述兩個函數的區別僅在於文件偏移量的類型不一樣,一個時是long,一個是off_t


off_t ftello(FILE *stream);
long ftell(FILE *stream);
功能:獲得內核中的文件偏移量
參數:stream:要獲取偏移量的文件流
返回值:成功返回文件從頭開始的偏移值,失敗返回-1
注:上述兩個函數的區別僅在於文件偏移量的類型不一樣,一個時是long,一個是off_t

void rewind(FILE *stream);
功能:定位到文件起始位置
參數:stream:要定位的文件流

  
int fileno(FILE *stream);
功能:獲得與流相關聯的文件描述符
參數:stream:要獲取描述符的流
返回值:返回與流相關聯的文件描述符


六、臨時文件

char *tmpnam(char *s);
功能:產生一個與現有文件名不同的一個有效路徑名字符串
參數:s:如果爲NULL,則將產生的路徑名存放在一個靜態區中。指向該靜態區的指針作爲函數值返回。下一次再調用該函數時,會重寫該靜態區。如果s不是NULL,則將產生的路徑名存放在s指向的空間中,s作爲函數返回值。
返回值:指向唯一路徑名的指針

FILE *tmpfile(void);
功能:創建一個臨時二進制文件(wb+),在關閉文件或進程結束時    將自動刪除這種文件
返回值:成功返回文件流指針,出錯返回NULL


























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