【APUE】標準I/O庫

本文章說明標準I/O庫
1.流和FILE對象
    對於文件IO都是針對於文件描述符的,但是對於標準I/O,則是針對於流進行的
    當用標準I/O庫打開一個文件的時候,我們已使一個流和一個文件相關聯
    對於ASCII字符集,一個字符用一個字節表示,對於國際字符,一個字符可用多個字節表示
    標準I/O文件流可用於單字節或多字節字符集
    流的定向決定了所讀、寫的文件是單字節還是多字節的,當一個流被創建的時候,它沒有被定向
    如果在沒有定向的流中使用多字節的I/O函數,則將該流的定向設置爲寬定向的
    如果在沒有定向的流中使用單字節的I/O函數,則將該流的定向設置爲字節定向
    fwide函數可以設置流的定向
    #include <stdio.h>
    #include <fchar.h>
    int fwide(FILE *fp, int mode);
    //若流是寬定向的返回正值,若流是字節定向的返回負值,若流是未定向的返回0
    若mode是正值,則函數試圖設置流爲寬定向的
    若mode是負值,則函數試圖設置流爲字節定向的
    若mode是0,則函數不設置流的定向,但是將返回標識該流定向的值
    注意fwide函數不設置已經定向的流

2.標準輸入,標準輸出和標準錯誤輸出
    在<stdio.h>中定義了這三個流stdin, stdout, stderr
    這三個流可以自動地被進程使用

3.緩衝
    標準I/O提供緩衝是爲了儘量減少read和write函數的調用
    標準I/O提供了三種類型的I/O
    (1)全緩衝
        當緩衝區全部寫滿的時候在進行寫入操作。
    (2)行緩衝
        當遇到換行符的時候進行寫入操作,或者遇到換行符之前,緩衝區填滿也進行寫入
    (3)不緩衝

    ISO C要求下列緩衝特性:
    當且僅當標準輸入輸出不涉及交互式設備的時候,它們纔是全緩衝的
    標準出錯決不是全緩衝的
    很多系統默認下列類型的緩衝特性:
    標準出錯不帶緩衝
    如若是涉及終端設備的其他流的時候,則它們是行緩衝的,否則是全緩衝的
    可以調用下面兩個函數更改緩衝類型:
    #include <stdio.h>
    void setbuf(FILE *restrict fp, char *restrict buf);
    int setvbuf(FILE *restrict fp, char *restrict buf, int mode, size_t size);
    //成功返回0,出錯返回非零值
    setbuf函數中,若buf非空,buf長度爲BUFSIZ,則緩衝類型是全緩衝或者行緩衝,當buf爲NULL的時候不緩衝
    setvbuf函數中,不同的mode有不同的處理方式
    _IOFBF    全緩衝,buf如下
        當buf非空,緩衝區爲長度爲size的用戶buf
        當buf爲BULL的時候,緩衝區爲合適長度的系統緩衝區
    _IOLBF    行緩衝,buf同理
    _IONBF    不緩衝,buf和size忽略
    強制沖洗一個流,將未寫入的數據都傳送給內核
    #include <stdio.h>
    int ffush(FILE *fp);
    //成功返回0,出錯返回EOF

4.打開流
    打開一個標準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, FILR *restrict fp);
    //在一個指定的流上打開一個指定的文件,如若該流已經打開,則先關閉該流,若該流已經定向,則清除
    FILE *fdopen(int filedesm const char *type);
    //將一個現有的文件描述符與一個標準I/O流結合起來
    //以上函數若成功返回文件指針,失敗返回NULL
    type指定對該I/O流的讀寫方式
    r或rb        爲讀而打開
    w或wb        把文件截短至0長,或爲寫而創建
    a或ab        追加,或爲寫而創建
    r+或r+b或rb+    爲讀和寫而打開
    w+或w+b或wb+    把文件截短至0長,或爲讀寫而打開
    a+或a+b或ab+    在文件尾讀和寫而打開或創建   
    b作爲type的一部分爲了區分文本文件和二進制文件,但是UNIX系統並不區分這兩種類型的文件,在UNIX下b是無用的
    fdopen在爲寫而打開的時候並不截短文件

    當以讀和寫類型打開一個文件的時候,有以下限制:
    如果中間沒有fflush、fseek、fsetpos和rewind的時候,則在輸出後面不能直接跟隨輸入
    如果中間沒有fseek、fsetpos或rewind,或者一個輸入操作沒有達到文件尾端,在輸入操作之後不能跟隨輸出

    調用fclose關閉一個打開的流
    #include <stdio.h>
    int fclose(FILE *fp);
    //成功返回0,出錯返回EOF

5.讀和寫流

    以下三個函數用於一次讀一個字符
    #include <stdio.h>
    int getc(FILE *fp);
    int fgetc(FILE *fp);
    int getchar(void);//等價與getc(stdin);
    //成功返回下一個字符,達到文件尾或出錯返回EOF
    爲了區分是否達到文件尾還是出錯,有以下函數
    #include <stdio.h>
    int ferror(FILE *fp);
    int feof(FILE *fp);
    //若條件爲真,返回非零值,否則返回0
    void clearerr(FILE *fp);//清除這兩個標誌
    可以調用下面的函數將已經讀出來的字符壓送會流中
    #include <stdio.h>
    int ungetc(int c, FILE *fp);
    //成功返回c,失敗返回EOF
    使用這個函數時,字符送到了流的緩衝區中
    輸出函數
    #include <stdio.h>
    int putc(int c, FILE *fp);
    int fputc(int c, FILE *fp);
    int putchar(int c);
    //成功返回buf,出錯返回EOF

6.每次一行I/O

    下面函數提供每次輸入一行的函數
    #include <stdio.h>
    char *fgets(char *restrict buf, int n, FILE *restrict fp);
    char *gets(char *buf);
    //成功返回buf,到達文件尾或失敗返回EOF
    //gets函數不安全,不建議使用
    每次輸出一行:
    #include <stdio.h>
    int fputs(const char *restrict str, FILE *restrict fp);
    int puts(const char *str);
    //成功返回非負值,出錯返回EOF

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);
    //返回讀和寫的對象數
    //nobj爲讀寫的對象數

8.格式化I/O
    格式化輸出函數
    #include <stdio.h>
    int printf(const char *restrict format, ...);
    int fprintf(FILE *restrict fp, 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, ...);
    //成功返回存入數組的字符數,失敗返回負值
    printf格式化寫到標準輸出
    fprintf格式化寫到指定的流
    sprintf和snprintf格式化寫到數組buf中
    格式化輸入函數
    #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

9.實現細節
    獲取一個流所對應的文件描述符
    #include <stdio.h>
    int fileno(FILE *fp);
    //返回與流相關的文件描述符

10.臨時文件
    創建臨時文件
    #include <stdio.h>
    char tmpnam(char *ptr);
    //返回唯一路徑名的指針
    FILE *tmpfile(void);
    //成功返回文件指針,失敗返回NULL

    每次調用tmpnam返回一個與文件名不同的有效路徑名字符串
    tmpfile產生一個臨時的二進制文件(wb+)。在關閉該文件或程序結束的時候將自動刪除這個文件。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章