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

C 語言文件操作函數完全手冊:18 個核心函數詳解與實戰代碼

     編輯:關於C語言

文件操作函數分類總覽

類別函數用途
打開/關閉fopen打開文件,返回 FILE*
fclose關閉文件,刷新緩衝區
fflush強制刷新輸出緩衝區
字符讀寫fgetc / getc讀單字符(函數/宏)
fputc / putc寫單字符
getchar / putchar標準輸入/輸出單字符
ungetc回退字符到輸入流
行/塊讀寫fgets讀一行(含換行符)
fputs寫字符串(不含結束符)
fread / fwrite二進制塊讀寫(結構體/數組)
定位/狀態fseek / ftell移動/獲取文件指針位置
rewind重置到文件開頭
feof / ferror / clearerr檢查 EOF/錯誤/清除標誌
格式化 I/Ofprintf / fscanf格式化讀寫
sprintf / sscanf字符串格式化(內存操作)

核心函數詳細參考

1. fopen - 打開文件


FILE *fopen(const char *path, const char *mode);

模式字符串:

  • r:只讀,文件必須存在
  • w:只寫,截斷或創建
  • a:追加寫,創建或末尾
  • +:讀寫雙向(r+, w+, a+)
  • b:二進制模式(Windows 區分換行符,Linux 忽略)

返回:成功返回 FILE*,失敗返回 NULL 並設置 errno。

2. 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);

適合結構體、數組整體讀寫。返回實際完成的項數(nmemb),size*nmemb 為總位元組數。

3. fseek / ftell - 隨機訪問


int fseek(FILE *stream, long offset, int whence);
long ftell(FILE *stream);

whence:SEEK_SET(開頭)、SEEK_CUR(當前)、SEEK_END(結尾)。ftell 返回當前偏移量,-1 表示錯誤。

4. feof / ferror - 狀態判斷


int feof(FILE *stream);      // 非零=已到 EOF
int ferror(FILE *stream);    // 非零=發生錯誤
void clearerr(FILE *stream); // 清除標誌

關鍵模式:讀取循環以 fread/fgets 返回值為判斷條件,不要 用 feof() 控制循環(會多讀一次)。

實戰演示:綜合文件操作範例


/**********************************************************************
 * 文件操作綜合演示
 * 編譯: gcc -Wall -o file_demo file_demo.c
 **********************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#define BUFSZ 256

int main() {
    FILE *fp;
    char buf[BUFSZ];
    long pos;
    size_t cnt;

    /* 1. 寫入文本文件 */
    fp = fopen("demo.txt", "w");
    if (!fp) { perror("fopen w"); return 1; }
    fprintf(fp, "第一行: Hello World\n");
    fprintf(fp, "第二行: 數字 %d %f\n", 42, 3.14);
    fputs("第三行: 直接寫入字符串\n", fp);
    fclose(fp);

    /* 2. 追加二進制數據 */
    struct { int id; double val; } records[3] = {
        {1, 1.1}, {2, 2.2}, {3, 3.3}
    };
    fp = fopen("demo.bin", "wb");
    if (!fp) { perror("fopen wb"); return 1; }
    cnt = fwrite(records, sizeof(records[0]), 3, fp);
    printf("寫入 %zu 條記錄\n", cnt);
    fclose(fp);

    /* 3. 文本讀取 - 行讀取 */
    fp = fopen("demo.txt", "r");
    if (!fp) { perror("fopen r"); return 1; }
    printf("=== 文本內容 ===\n");
    while (fgets(buf, BUFSZ, fp)) {
        printf("%s", buf);  // fgets 保留 \n
    }
    fclose(fp);

    /* 4. 二進制讀取 - 隨機訪問 */
    fp = fopen("demo.bin", "rb");
    if (!fp) { perror("fopen rb"); return 1; }
    
    // 移動到第 2 條記錄
    fseek(fp, 1 * sizeof(records[0]), SEEK_SET);
    struct { int id; double val; } rec;
    cnt = fread(&rec, sizeof(rec), 1, fp);
    if (cnt == 1) {
        printf("第 2 條記錄: id=%d, val=%.1f\n", rec.id, rec.val);
    }
    
    // 獲取文件大小
    fseek(fp, 0, SEEK_END);
    long fsize = ftell(fp);
    printf("文件大小: %ld 位元組\n", fsize);
    fclose(fp);

    /* 5. 錯誤處理演示 */
    fp = fopen("not_exist.txt", "r");
    if (!fp) {
        printf("預期錯誤: %s (errno=%d)\n", strerror(errno), errno);
    }

    return 0;
}

高頻錯誤與最佳實踐

錯誤模式後果正確做法
未檢查 fopen 返回值空指針解引用崩潰必檢查,失敗打印 strerror(errno)
feof 控制讀取循環多處理一次 EOF 數據以 fread/fgets 返回值為循環條件
文本模式讀二進制Windows 換行符轉換損壞數據二進制文件用 "rb"/"wb"
忘記 fclose緩衝區未刷新、文件描述符洩漏配對 fclose,異常路徑也要關閉
緩衝區溢出gets/fscanf 不限長度用 fgets/snprintf,指定尺寸
ftell 用於文本流Windows 下位置不準僅二進制流用 ftell/fseek

進階主題

  • 大文件支持:fseeko/ftello (off_t)、fopen64、編譯加 -D_FILE_OFFSET_BITS=64
  • 線程安全:flockfile/funlockfile 鎖定 FILE*,或用 fread_unlocked 等無鎖版本配合外部鎖
  • 內存映射:mmap() 大文件隨機訪問性能更優,屬 POSIX 而非標準 C
  • 臨時文件:tmpfile() 自動刪除、mkstemp() 安全創建
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved