C語言中文網 目錄

C語言文件的打開和關閉,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++STLLinuxShellJavaGo語言等教程,以及socketGCCviSwing設計模式JSP等專題。

Copyright ?2011-2018 biancheng.net, 陜ICP備15000209號

底部Logo