首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C 語言文件操作完整實戰:文本/二進制讀寫、結構體序列化、動態內存配合

     編輯:關於C語言

C 語言文件操作完整實戰

文件 I/O 是 C 語言持久化數據的核心手段。本文通過一個完整示例,演示文本模式格式化讀寫、二進制模式結構體批量讀寫、動態內存配合文件操作的標準流程與錯誤處理。

核心 API 速查

函數用途模式
fopen打開文件,返回 FILE*"r"/"w"/"a"/"rb"/"wb"/"ab"
fclose關閉文件,刷新緩衝區—
fprintf/fscanf格式化文本讀寫文本
fread/fwrite二進制塊讀寫二進制
fputc/fgetc單字符讀寫文本
feof/ferror檢查結束/錯誤狀態—

完整示例程序

#include 
#include 

#define N 2

typedef struct {
    char Class[20];
    int age;
    char name[9];
} Student;

int main() {
    FILE *fp;
    int i, n;
    char Class[20], name[9];
    int age;

    /* === 1. 文本模式:寫入固定條數學生記錄 === */
    printf("將學生信息寫入文本文件:\n");
    fp = fopen("E:\\c\\stu.txt", "w");
    if (!fp) { perror("fopen write"); return 1; }

    for (i = 0; i < N; i++) {
        printf("學生班級: "); scanf("%19s", Class);
        printf("學生年齡: "); scanf("%d", &age);
        printf("學生姓名: "); scanf("%8s", name);
        fprintf(fp, "%s %6d %10s\n", Class, age, name);
    }
    fclose(fp);

    /* === 2. 文本模式:讀取並顯示 === */
    printf("\n從文本文件讀取學生信息:\n");
    fp = fopen("E:\\c\\stu.txt", "r");
    if (!fp) { perror("fopen read"); return 1; }

    for (i = 0; i < N; i++) {
        if (fscanf(fp, "%19s %d %8s", Class, &age, name) != 3) break;
        printf("班級:%s, 年齡:%d, 姓名:%s\n", Class, age, name);
    }
    fclose(fp);

    /* === 3. 二進制模式:動態分配結構體數組,追加寫入 === */
    printf("\n向二進制文件追加學生信息:\n");
    fp = fopen("E:\\c\\stu.dat", "wb");  // wb 截斷重寫,ab 則追加
    if (!fp) { perror("fopen wb"); return 1; }

    printf("追加記錄數: "); scanf("%d", &n);
    Student *students = (Student*)malloc(sizeof(Student) * n);
    if (!students) { perror("malloc"); fclose(fp); return 1; }

    for (i = 0; i < n; i++) {
        printf("第 %d 筆 - 班級: ", i+1); scanf("%19s", students[i].Class);
        printf("第 %d 筆 - 年齡: ", i+1); scanf("%d", &students[i].age);
        printf("第 %d 筆 - 姓名: ", i+1); scanf("%8s", students[i].name);
    }

    // 批量寫入:返回成功寫入的元素個數
    if (fwrite(students, sizeof(Student), n, fp) != n) {
        fprintf(stderr, "文件寫入失敗!\n");
    }
    fclose(fp);
    free(students);

    /* === 4. 二進制模式:讀取並顯示 === */
    printf("\n從二進制文件讀取學生信息:\n");
    fp = fopen("E:\\c\\stu.dat", "rb");
    if (!fp) { perror("fopen rb"); return 1; }

    // 重新分配內存接收數據
    students = (Student*)malloc(sizeof(Student) * n);
    if (!students) { perror("malloc"); fclose(fp); return 1; }

    if (fread(students, sizeof(Student), n, fp) != n) {
        fprintf(stderr, "文件讀取失敗或數據不全!\n");
    } else {
        for (i = 0; i < n; i++) {
            printf("班級:%s, 年齡:%d, 姓名:%s\n",
                   students[i].Class, students[i].age, students[i].name);
        }
    }
    fclose(fp);
    free(students);
    return 0;
}

關鍵技術點解析

1. 文本 vs 二進制模式

  • 文本:人類可讀,跨平台換行符轉換(Windows \r\n ↔ \n),適合配置、日志、CSV。
  • 二進制:內存位模像直接存取,速度快、體積小、精確保留結構體佈局(含填充字節),適合高性能數據交換、結構體序列化。

2. 結構體二進制讀寫注意事項

  1. 結構體佈局一致性:讀寫雙端編譯器、對齊屬性(#pragma pack)、結構體定義必須完全一致。
  2. 指針成員不可直接序列化:指針存儲的是地址,重讀後無效。需序列化指向的實際數據(如字符串長度+內容)。
  3. 端序問題:跨架構傳輸需統一網絡序(htonl/ntohl)。
  4. 版本演進:文件頭加版本號/魔數,支持向後兼容。

3. 動態內存與文件操作配合

  • 讀取前先分配足夠內存(malloc/calloc)。
  • fread/fwrite 返回值**必須檢查**,確認實際處理元素數。
  • 使用後及時 free,避免洩漏。

4. 錯誤處理最佳實踐

fp = fopen(path, "rb");
if (!fp) { perror("fopen"); return -1; }  // perror 自動打印 errno 信息

if (fread(buf, size, count, fp) != count) {
    if (feof(fp)) fprintf(stderr, "意外到達文件末尾\n");
    else if (ferror(fp)) perror("fread");
    else fprintf(stderr, "數據不完整\n");
}

運行結果示例

將學生信息寫入文本文件:
學生班級: Class1
學生年齡: 20
學生姓名: Alice
學生班級: Class2
學生年齡: 21
學生姓名: Bob

從文本文件讀取學生信息:
班級:Class1, 年齡:20, 姓名:Alice
班級:Class2, 年齡:21, 姓名:Bob

向二進制文件追加學生信息:
追加記錄數: 2
第 1 筆 - 班級: Class3
第 1 筆 - 年齡: 22
第 1 筆 - 姓名: Carol
第 2 筆 - 班級: Class4
第 2 筆 - 年齡: 23
第 2 筆 - 姓名: Dave

從二進制文件讀取學生信息:
班級:Class3, 年齡:22, 姓名:Carol
班級:Class4, 年齡:23, 姓名:Dave

掌握文本/二進制雙模式、結構體序列化邊界條件、動態內存安全配合,即可應對絕大多數 C 語言文件持久化場景。

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