文件操作核心流程
fopen 打開 → 返回 FILE*
fread/fwrite/fgetc/fputc/fgets/fputs 讀寫
fseek/ftell/rewind 定位
fclose 關閉,刷新緩衝區、釋放資源
函數速查表
| 函數 | 原型 | 說明 | 返回值 |
| fopen | FILE* fopen(const char* path, const char* mode) | 打開文件。mode: r/w/a/r+/w+/a+ 可加 b(二進制) | 成功: FILE*;失敗: NULL |
| fclose | int fclose(FILE* stream) | 關閉文件,刷新緩衝區 | 成功: 0;失敗: EOF |
| fread | size_t fread(void* ptr, size_t size, size_t nmemb, FILE* stream) | 讀取 nmemb 個 size 字節元素 | 實際讀取元素數 |
| fwrite | size_t fwrite(const void* ptr, size_t size, size_t nmemb, FILE* stream) | 寫入 nmemb 個 size 字節元素 | 實際寫入元素數 |
| fseek | int fseek(FILE* stream, long offset, int whence) | 移動文件指針。whence: SEEK_SET/CUR/END | 成功: 0;失敗: -1 |
| ftell | long ftell(FILE* stream) | 獲取當前文件指針位置 | 位置(字節偏移);錯誤: -1 |
| rewind | void rewind(FILE* stream) | 指針歸零,清除錯誤標誌 | 無 |
| fgetc | int fgetc(FILE* stream) | 讀取一字符 | 字符值;EOF |
| fputc | int fputc(int c, FILE* stream) | 寫入一字符 | 寫入字符;EOF |
| fgets | char* fgets(char* s, int size, FILE* stream) | 讀取一行(含換行符),最多 size-1 字符 | s;EOF/錯誤: NULL |
| fputs | int fputs(const char* s, FILE* stream) | 寫入字符串(不含結束符) | 非負數;EOF |
| feof | int feof(FILE* stream) | 檢測文件結束標誌 | 非零: 已到末尾 |
| ferror | int ferror(FILE* stream) | 檢測錯誤標誌 | 非零: 有錯誤 |
| clearerr | void clearerr(FILE* stream) | 清除錯誤和EOF標誌 | 無 |
| fflush | int fflush(FILE* stream) | 刷新輸出緩衝區 | 成功: 0;失敗: EOF |
| setbuf | void setbuf(FILE* stream, char* buf) | 設置緩衝區。buf=NULL → 無緩衝 | 無 |
| setvbuf | int setvbuf(FILE* stream, char* buf, int mode, size_t size) | 精確控制緩衝。mode: _IOFBF/_IOLBF/_IONBF | 成功: 0;失敗: 非零 |
| ftello/fseeko | off_t ftello(FILE*) / int fseeko(FILE*, off_t, int) | 大文件支持 (LFS),off_t 為 64位 | 同 ftell/fseek |
| fileno | int fileno(FILE* stream) | 獲取底層文件描述符 | fd;錯誤: -1 |
| fdopen | FILE* fdopen(int fd, const char* mode) | 文件描述符轉 FILE* | FILE*;NULL |
| freopen | FILE* freopen(const char* path, const char* mode, FILE* stream) | 重新關聯流到新文件 | FILE*;NULL |
| tmpfile | FILE* tmpfile(void) | 創建臨時二進制文件,關閉自動刪除 | FILE*;NULL |
| tmpnam | char* tmpnam(char* s) | 生成唯一臨時文件名 | 指向名稱緩衝區 |
| remove | int remove(const char* path) | 刪除文件 | 成功: 0 |
| rename | int rename(const char* old, const char* new) | 重命名/移動文件 | 成功: 0 |
關鍵模式字符串
| mode | 含義 | 文件須存在 | 寫入位置 |
r | 只讀 | 是 | - |
w | 只寫,截斷/創建 | 否 | 開頭 |
a | 追加寫入 | 否 | 末尾 |
r+ | 讀寫 | 是 | 開頭 |
w+ | 讀寫,截斷/創建 | 否 | 開頭 |
a+ | 讀寫,追加 | 否 | 末尾 |
加 b 表示二進制模式 (Windows 關鍵,Linux 忽略)。
經典讀寫模式
文本逐行讀取
FILE *fp = fopen("data.txt", "r");
char line[256];
while (fgets(line, sizeof(line), fp)) {
// 處理 line (含 \n)
}
fclose(fp);
二進制結構體數組讀寫
struct Record { char name[20]; int id; };
struct Record recs[100];
// 寫入
FILE *fp = fopen("data.bin", "wb");
fwrite(recs, sizeof(struct Record), 100, fp);
fclose(fp);
// 讀取
fp = fopen("data.bin", "rb");
size_t cnt = fread(recs, sizeof(struct Record), 100, fp);
fclose(fp);
隨機訪問:修改第 5 條記錄
fp = fopen("data.bin", "r+b");
fseek(fp, 4 * sizeof(struct Record), SEEK_SET);
fwrite(&new_rec, sizeof(struct Record), 1, fp);
fclose(fp);
錯誤處理模式
FILE *fp = fopen("file.txt", "r");
if (!fp) {
perror("fopen failed"); // 打印 errno 對應信息
return -1;
}
// ... 操作 ...
if (ferror(fp)) {
fprintf(stderr, "I/O error\n");
}
fclose(fp);
緩衝區模式選擇
_IOFBF (全緩衝):填滿刷新,適合大文件順序讀寫
_IOLBF (行緩衝):遇換行刷新,適合終端交互
_IONBF (無緩衝):立即寫入,調試/日志/關鍵數據
大文件支持 (LFS)
- 編譯加
-D_FILE_OFFSET_BITS=64
- 使用
ftello/fseeko、off_t 替代 long
- 支持 >2GB 文件操作