天天看點

【硬核知識】C語言檔案操作!檔案的打開和關閉!

檔案代表一系列的位元組。函數 fopen()将一個檔案和一個流關聯起來,并初始化一個類型為 FILE 的對象,該對象包含了控制該流的所有資訊。這些資訊包括指向緩沖區的指針;檔案位置訓示器,它指定了擷取檔案的位置;以及訓示錯誤和檔案結尾情況的标志。

每個用于打開檔案的函數(也就是 fopen()、freopen()和 tmpfile())都會傳回一個指向 FILE 對象的指針,該 FILE 對象包含與被打開檔案相關聯的流。一旦打開了檔案,就可以調用函數傳遞資料并對流進行處理。這些函數都把指向 FILE 對象的指針(通常稱為 FILE 指針)作為它們的參數之一。FILE 指針指定了正在進行操作的流。

I/O 連結庫也包含了用于操作檔案系統的函數,這些函數把檔案名作為它們的參數之一。使用這些函數不需要事先打開檔案。它們包括:

        (1) 函數 remove()删除一個檔案(或者空目錄)。該字元串參數是檔案名。如果檔案具有多個名稱,那麼 remove()隻會删除所指定的名稱,而非删除檔案本身。該檔案資料還可以通過别的方式來擷取,但是不能通過已删除的檔案名通路。

        (2) 函數 rename()改變一個檔案(或目錄)的名稱。該函數的兩個字元串參數依次為舊檔案名和新檔案名。函數 remove()和 rename()的傳回值類型都是 int,成功時都會傳回 0,失敗時都會傳回非 0值,下面的語句将 songs.dat 重命名為 mysong.dat:

if ( rename( "songs.dat", "mysongs.dat" ) != 0 )   fprintf( stderr, "Error renaming \"songs.dat\".\n );

導緻函數 rename()失敗的原因包括:使用舊檔案名的檔案不存在;程式擷取檔案的權限不夠;或者檔案已經被打開。至于具體何種格式的檔案名才是合法的,這是由實作版本決定。

無論是新檔案或已有檔案,首先必須打開該檔案,才可以向檔案中寫入資料,或者修改其中的内容。打開一個檔案時,必須指定通路模式(access mode),以表明計劃對該檔案進行的是讀、寫或讀寫結合等操作。當使用完該檔案後,必須關閉它以釋放資源。

标準庫提供函數 fopen()用以打開檔案(在特殊情況下,還可以使用函數 freopen()和 tmpfile()來打開檔案):

FILE *fopen( const char * restrict filename,             const char * restrict mode );

字元串 filename 向該函數傳入所需打開的檔案的名稱。該檔案名字元串也可以包含目錄資訊,但必須保證字元串長度不得超過宏 FILENAME_MAX 中指定的最大長度。函數的第二個參數 mode 也是一個字元串,用來指定檔案通路模式。函數 freopen()會把檔案與一個新的流關聯起來。

FILE *freopen(const char * restrict filename,               const char * restrict mode,               FILE * restrict stream );

該函數将一個流重新定向。與 fopen()類似,freopen()也會用指定的通路模式打開指定的檔案。但不同的是,freopen()不會建立新的流,而是将檔案與已有的流關聯,已有的流通過該函數的第三個參數指定。之前與該流關聯的檔案會被關閉。freopen()常被用來重新定向到标準流 stdin、stdout 和 stderr。

FILE *tmpfile( void );

函數 tmpfile()會建立一個新的臨時檔案,其檔案名與所有已有檔案名都不一樣,然後打開該檔案,進行二進制資料的讀寫操作(類似于函數 fopen()采用“wb+”通路模式)。如果該程式正常地結束,該檔案會被自動删除。

所有三個打開檔案的函數 fopen()、freopen()和 tmpfile(),都會傳回一個指針。如果成功,該指針就指向已打開的流,如果失敗,該指針就為空指針。

如果一個檔案打開用于寫操作,程式應賦予其獨立通路權限以防止其他程式同時對該檔案進行寫操作。傳統的标準函數并不能確定獨立檔案通路權限,但是 C11 新增的三個新“安全”函數 fopen_s()、freopen_s()和 tmpfile_s(),在作業系統支援的前提下,可以提供獨立通路權限。

函數 fopen()和 freopen()的第二個參數指定了檔案的通路模式,通路模式決定了流所許可的輸入和輸出操作。對通路模式字元串的許可值有嚴格的限制。該字元串的第一個字元隻能為三種形式:r(表示“read”)、w(表示“write”)或者 a(表示“append”)。

在最簡單情況下,該字元串隻包含一個字元。模式字元串還可以包含 + 和 b(如果兩者同時具有,次序是沒有關系的,+b 效果等同于 b+)。

模式字元串中的加号(+)表示讀寫操作都可以進行。然而,程式不可以在讀操作和寫操作之間立即作切換。在寫操作之後,必須調用函數 fflush()或者定位函數(fseek()、fsetpos()或 rewind()),然後才可以執行讀操作。在讀操作之後,必須調用定位函數,然後才可以執行寫操作。

模式字元串中的 b 表示檔案以二進制模式打開。也就是說,與該檔案關聯的流是二進制流。如果模式字元串中沒有 b,建立立的流就是字元串流。

當模式字元串以 r 開始時,該檔案必須已經存在于檔案系統中。當模式字元串以 w 開始時,如果檔案不存在,則會建立一個新檔案;如果檔案存在,該檔案目前内容會被清除,因為在“write”模式中,函數 fopen()将檔案長度設定為 0。

C11 新增一個功能,在作業系統支援的前提下,允許在獨立寫操作模式下打開檔案。可以在以 w 起始的模式字元串中使用字尾 x,例如 wx 或 w+bx,以指定獨立通路權限。如果檔案已經存在或者不能被建立,則檔案打開函數執行失敗(傳回空指針)。否則,将建立檔案并以獨立通路權限打開它。

當模式字元串以 a 開始時,如果檔案不存在,則也會建立一個新檔案。如果檔案存在,該檔案目前内容會被保留,因為所有新寫入的内容都會從檔案尾端添加。

下面是一個簡單的示例:

#include <stdio.h> #include <stdbool.h> _Bool isReadWriteable( const char *filename ) {   FILE *fp = fopen( filename, "r+" );  // 打開一個檔案以用于讀寫   if ( fp != NULL )                            // fopen()是否執行成功   {     fclose(fp);                                // 成功:關閉檔案,沒有錯誤需要處理     return true;   }   else                                          // 失敗     return false; }

上例也展示了如何利用函數 fclose()關閉一個檔案。

關閉檔案時需要使用函數 fclose(),該函數的原型是:

int fclose( FILE *fp );

該函數把緩沖區記憶體在的所有資料儲存到檔案中,關閉檔案,釋放所有用于該流輸入輸出緩沖區的記憶體。函數 fclose()傳回 0 表示成功,傳回 EOF 表示産生錯誤。

當程式退出時,所有打開的檔案都會自動關閉。盡管如此,還是應該在完成檔案處理後,主動關閉檔案。否則,一旦遇到非正常的程式終止,就可能會丢失資料。而且,一個程式可以同時打開的檔案數量是有限的,數量上限小于等于常量 FOPEN_MAX 的值。

【硬核知識】C語言檔案操作!檔案的打開和關閉!

不管你是轉行也好,初學也罷,進階也可,如果你想學程式設計,進階程式員~

C語言入門資料(網盤連結免費分享):

【硬核知識】C語言檔案操作!檔案的打開和關閉!

C語言推薦書籍(PDF免費分享):

【硬核知識】C語言檔案操作!檔案的打開和關閉!

繼續閱讀