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

C 語言文件操作教程(六):數據塊讀寫 fread/fwrite 與格式化讀寫 fprintf/fscanf 實戰對比

     編輯:關於C語言

前言

文件讀寫除字節/字符串外,尚有**數據塊** (結構體、數組) 與 **格式化** 兩大高級模式。本文以「學生信息存取」為案例,對比 fread/fwrite 二進制塊操作與 fprintf/fscanf 文本格式化操作的代碼結構、文件形態、適用場景。

一、數據塊讀寫:fread/fwrite

1. 函數原型

size_t fread(void *buf, size_t size, size_t count, FILE *fp);
size_t fwrite(const void *buf, size_t size, size_t count, FILE *fp);
  • buf:緩衝區首地址 (讀入目標 / 寫出源)。
  • size:單個數據項位元組數 (如 sizeof(struct Stu))。
  • count:項目數 (如陣列長度)。
  • 返回值:成功讀寫的項目數。
  • 位置指示器自動前移 size * count 位元組。

2. 範例:結構體數組二進制存取

#include 
#include 

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

int main() {
    FILE *fp;
    int i;
    pp = boya; qq = boyb;

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

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

    pp = boya;
    fwrite(pp, sizeof(struct Stu), 2, fp);  // 一次寫入 2 條記錄

    rewind(fp);                              // 歸零位置指針
    fread(qq, sizeof(struct Stu), 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);
    return 0;
}

3. 關鍵特點

  • **二進制文件** (wb+/rb+),內容不可直接閱讀,但**讀寫極快、空間緊湊、保持記憶體位模式**。
  • 一次調用可處理**整個陣列/結構體**,無需循環。
  • rewind(fp) 等價 fseek(fp, 0, SEEK_SET),配合隨機讀寫。
  • **跨平台隱患**:結構體填充/對齊/字節序差異導致文件格式不兼容。

二、格式化讀寫:fprintf/fscanf

1. 函數原型

int fprintf(FILE *fp, const char *format, ...);
int fscanf(FILE *fp, const char *format, ...);
  • 功能同 printf/scanf,但目標為文件而非標準輸入輸出。
  • fprintf 返回輸出字符數;fscanf 返回成功賦值的項目數 (EOF 表示失敗/結束)。

2. 範例:同樣學生信息,文本格式存取

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

/* 讀取部分 */
rewind(fp);
for (i = 0; i < 2; i++, qq++)
    fscanf(fp, "%s %d %d %s\n", qq->name, &qq->num, &qq->age, qq->addr);

3. 關鍵差異對比

維度fread/fwrite (二進制塊)fprintf/fscanf (文本格式化)
文件類型二進制 (wb/rb)文本 (w/r 或 wt/rt)
可讀性不可直接閱讀**人類可讀**,可用編輯器查看/修改
空間效率高 (無分隔符、無格式開銷)低 (空格、換行、數字字符化)
速度極快 (內存映射式)較慢 (格式解析/轉換開銷)
跨平台**差** (對齊/字節序/類型大小)**優** (文本通用標準)
精度**無損** (位模式完整保存)浮點數可能有微小誤差 (文本轉換)
代碼結構單次調用處理整陣列**需循環逐項處理** (格式串對應單項)
指針管理陣列名/指針不變循環中指針遞增,**用後需重置首地址**

三、指針重置陷阱 (fscanf/fprintf 循環專有)

pp = boya;
for (i=0; i<2; i++, pp++) fprintf(fp, "...", pp->...);  // pp 移至末尾

rewind(fp);
for (i=0; i<2; i++, qq++) fscanf(fp, "...", qq->...);  // qq 移至末尾

/* 後續若再次使用 pp/qq,必須重置: */
pp = boya; qq = boyb;

二進制塊操作無此問題,因不修改指針值。

四、選擇指南

  • 內部數據交換、高性能日誌、嵌入式固件 → fread/fwrite 二進制塊。
  • 配置文件、數據導出給人工/他語言處理、跨平台交換 → fprintf/fscanf 文本格式化。
  • 混合策略:索引/元數據用文本,大數據塊用二進制 (如 WAV/MP4/BMP 文件結構)。

總結

fread/fwrite 以**內存位模式**直接落盤,快且緊湊但脆弱;fprintf/fscanf 以**文本協議**序列化,慢且冗餘但通用健壯。理解「單次調用 vs 循環逐項」、「指針是否自增」、「跨平台兼容性」三大核心差異,根據場景果斷選型,是 C 文件編程的進階標誌。

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