首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

C 語言檔案讀寫入門:fopen 模式與指標定位詳解

     編輯:程式設計疑難解答

C 語言檔案操作是系統程式設計的基石。新手常在「寫入正常但讀取失敗」或「二次開啟檔案失敗」上卡關。本文從檔案指標、開啟模式、緩衝區機制三個維度,徹底講透檔案讀寫核心邏輯。

檔案指標與位置指標

每個 `FILE*` 指標內部維護一個位置指標(position indicator),記錄下一次讀寫的位置。關鍵操作對位置指標的影響:

  • `fopen(..., "r")`:位置指標指向檔案開頭。
  • `fopen(..., "a")`:位置指標指向檔案結尾(附加模式)。
  • `fwrite`/`fprintf` 寫入 N 字節 → 位置指標後移 N 字節。
  • `fread`/`fscanf` 讀取 N 字節 → 位置指標後移 N 字節。
  • `rewind(fp)` / `fseek(fp, 0, SEEK_SET)` → 位置指標歸零。

為何「寫完讀不到」?

FILE *fp = fopen("data.txt", "w");
fprintf(fp, "Hello");  // 寫入 5 字節,位置指標在第 5 字節後
// 此時直接 fgets/fread 會讀到 EOF,因為指標已在檔尾!

// 正確做法:重置指標
rewind(fp);  // 或 fseek(fp, 0, SEEK_SET)
char buf[100];
fgets(buf, sizeof(buf), fp); // 正常讀到 "Hello"

為何「第二次 fopen 失敗」?

常見原因:

  1. 未關閉先前檔案指標:同一程式對同一檔案多次 `fopen` 而未 `fclose`,導致檔案描述符洩漏,超出進程限制(通常 1024/4096)。
  2. 模式衝突:首次以 `"w"` 開啟截斷檔案,第二次以 `"r"` 開啟前未 `fclose`,檔案可能被鎖定或狀態不一致。
  3. 路徑錯誤:相對路徑依賴當前工作目錄,`chdir` 或 IDE 執行目錄不同導致找不到檔案。建議使用絕對路徑或 `getcwd()` 確認。
  4. 檔名無副檔名:Windows 預設隱藏副檔名,實際檔名可能為 `data.txt.txt`,程式中寫 `data.txt` 自然找不到。

標準檔案操作範本

#include 
#include 

int main() {
    const char *filename = "data.txt";
    FILE *fp = NULL;
    char buffer[256];
    
    // 1. 寫入
    fp = fopen(filename, "w");
    if (!fp) { perror("fopen write failed"); return 1; }
    fprintf(fp, "Line 1\nLine 2\nLine 3\n");
    fclose(fp); // 必須關閉,釋放鎖定、刷新緩衝區
    
    // 2. 讀取(逐行)
    fp = fopen(filename, "r");
    if (!fp) { perror("fopen read failed"); return 1; }
    while (fgets(buffer, sizeof(buffer), fp)) {
        printf("讀到:%s", buffer); // fgets 保留換行符
    }
    fclose(fp);
    
    // 3. 附加模式
    fp = fopen(filename, "a");
    if (!fp) { perror("fopen append failed"); return 1; }
    fprintf(fp, "Appended line\n");
    fclose(fp);
    
    // 4. 二進位模式範例(結構體讀寫)
    struct Student { int id; char name[20]; float score; } s = {1, "Tom", 92.5};
    fp = fopen("student.dat", "wb");
    if (fp) { fwrite(&s, sizeof(s), 1, fp); fclose(fp); }
    
    fp = fopen("student.dat", "rb");
    if (fp) { fread(&s, sizeof(s), 1, fp); fclose(fp); }
    
    return 0;
}

進階:緩衝區與 `fflush`

  • 標準 I/O 預設全緩衝(檔案)、行緩衝(終端)、無緩衝(stderr)。
  • 關鍵資料寫入後呼叫 `fflush(fp)` 強制落盤,防止程式崩潰導致資料遺失。
  • `setvbuf(fp, NULL, _IONBF, 0)` 可關閉緩衝(除錯用)。

錯誤處理黃金法則

  1. 每次 `fopen`、`fread`、`fwrite`、`fseek` 後**必須檢查回傳值**。
  2. 使用 `perror()` 或 `strerror(errno)` 輸出具體錯誤原因。
  3. 區分 `feof(fp)`(真正讀到檔尾)與 `ferror(fp)`(讀取出錯)。

掌握檔案指標位置、緩衝區特性與嚴謹的錯誤檢查,C 語言檔案操作就不再是「玄學」,而是可控、可預測的工程技能。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved