文件讀寫除字節/字符串外,尚有**數據塊** (結構體、數組) 與 **格式化** 兩大高級模式。本文以「學生信息存取」為案例,對比 fread/fwrite 二進制塊操作與 fprintf/fscanf 文本格式化操作的代碼結構、文件形態、適用場景。
fread/fwritesize_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 位元組。#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;
}
wb+/rb+),內容不可直接閱讀,但**讀寫極快、空間緊湊、保持記憶體位模式**。rewind(fp) 等價 fseek(fp, 0, SEEK_SET),配合隨機讀寫。fprintf/fscanfint fprintf(FILE *fp, const char *format, ...);
int fscanf(FILE *fp, const char *format, ...);
printf/scanf,但目標為文件而非標準輸入輸出。fprintf 返回輸出字符數;fscanf 返回成功賦值的項目數 (EOF 表示失敗/結束)。/* 寫入部分 */
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);
| 維度 | fread/fwrite (二進制塊) | fprintf/fscanf (文本格式化) |
|---|---|---|
| 文件類型 | 二進制 (wb/rb) | 文本 (w/r 或 wt/rt) |
| 可讀性 | 不可直接閱讀 | **人類可讀**,可用編輯器查看/修改 |
| 空間效率 | 高 (無分隔符、無格式開銷) | 低 (空格、換行、數字字符化) |
| 速度 | 極快 (內存映射式) | 較慢 (格式解析/轉換開銷) |
| 跨平台 | **差** (對齊/字節序/類型大小) | **優** (文本通用標準) |
| 精度 | **無損** (位模式完整保存) | 浮點數可能有微小誤差 (文本轉換) |
| 代碼結構 | 單次調用處理整陣列 | **需循環逐項處理** (格式串對應單項) |
| 指針管理 | 陣列名/指針不變 | 循環中指針遞增,**用後需重置首地址** |
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 文本格式化。fread/fwrite 以**內存位模式**直接落盤,快且緊湊但脆弱;fprintf/fscanf 以**文本協議**序列化,慢且冗餘但通用健壯。理解「單次調用 vs 循環逐項」、「指針是否自增」、「跨平台兼容性」三大核心差異,根據場景果斷選型,是 C 文件編程的進階標誌。