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

C 語言檔案操作教程(十):資料塊讀寫 fread/fwrite 與格式化 fprintf/fscanf 完整指南

     編輯:C 語言基礎

二進位資料塊 I/O:fread / fwrite

適用於結構體、陣列、任意記憶體區塊的高效讀寫,不做格式轉換,直接搬移位元組。

函數原型


size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
  • ptr:緩衝區位址 (讀入目標 / 寫出來源)。
  • size:單一元素大小 (位元組)。
  • nmemb:元素個數。
  • 回傳實際成功元素數 (可能 < nmemb)。

範例:結構體陣列二進位寫入/讀出


#include 
#include 

struct Student {
    char name[10];
    int  num;
    int  age;
    char addr[15];
} boya[2], boyb[2], *pp, *qq;

int main(void)
{
    FILE *fp;
    int i;

    pp = boya; qq = boyb;

    if ((fp = fopen("stu_list", "wb+")) == NULL) {
        printf("Cannot open file"); getch(); return 1;
    }

    printf("\ninput data\n");
    for (i = 0; i < 2; ++i, ++pp)
        scanf("%9s%d%d%14s", pp->name, &pp->num, &pp->age, pp->addr);

    pp = boya;
    fwrite(pp, sizeof(struct Student), 2, fp);  /* 一次寫 2 筆 */

    rewind(fp);
    fread(qq, sizeof(struct Student), 2, fp);   /* 一次讀 2 筆 */

    printf("\n\nname\tnum\tage\taddr\n");
    for (i = 0; i < 2; ++i, ++qq)
        printf("%s\t%5d\t%7d\t%s\n", qq->name, qq->num, qq->age, qq->addr);

    fclose(fp);
    getch();
    return 0;
}

格式化檔案 I/O:fprintf / fscanf

對應 printf/scanf,但目標為 FILE*。適合人類可讀的文字檔 (CSV、設定檔、日誌)。


int fprintf(FILE *stream, const char *format, ...);
int fscanf(FILE *stream, const char *format, ...);

同樣任務用 fprintf/fscanf 實作


/* 寫入 */
for (i = 0, pp = boya; i < 2; ++i, ++pp)
    fprintf(fp, "%s %d %d %s\n", pp->name, pp->num, pp->age, pp->addr);

/* 讀出 */
rewind(fp);
for (i = 0, qq = boyb; i < 2; ++i, ++qq)
    fscanf(fp, "%9s %d %d %14s", qq->name, &qq->num, &qq->age, qq->addr);

三種模式深度對比

維度fread/fwrite (二進位塊)fprintf/fscanf (格式化文字)fgetc/fputc/fgets/fputs (字元/行)
檔案類型二進位 ("rb"/"wb")文字 ("rt"/"wt")文字/二進位皆可
資料表達記憶體原貌 (含 padding)人類可讀字串字串/字元
跨平台可攜性低 (端序、對齊、型別大小)高 (純文字)高
效能最高 (無轉換)中 (格式解析/生成)中低
適用場景高效能資料庫、影像、序列化設定檔、CSV、日誌、除錯輸出逐行處理、簡單文字
結構體直接存取是 (一次寫整個 struct)需逐欄位需逐欄位

關鍵細節與避坑指南

  1. 結構體填充:sizeof(struct Student) 可能大於成員總和 (對齊 padding)。二進位檔跨平台讀取會失敗,僅限同編譯器/同架構。
  2. 指標/動態記憶體不可直接 fwrite:會寫入位址值而非內容。需序列化 (扁平化) 或逐欄位寫入。
  3. fscanf 格式字串需匹配空白:"%s %d" 會吞噬任意空白;"%s,%d" 則要求逗號分隔。
  4. 迴圈中指標遞增:範例中 pp++ 導致指標偏移,後續使用前必須 pp = boya; 重置。
  5. 錯誤檢查:if (fread(...) != expected_count) { if (feof(fp)) ...; else ...; }
  6. 文字模式換行轉換:Windows "wt" 寫入 \n 會變 \r\n,讀入反向;二進位模式無轉換。

現代序列化替代方案

  • Protocol Buffers / FlatBuffers / MessagePack:跨語言、版本相容、高效二進位。
  • JSON (cJSON, Jansson):人類可讀、通用、較大。
  • SQLite:嵌入式關聯式資料庫,ACID、查詢能力強。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved