文件操作是持久化數據的關鍵。本文聚焦兩大主題:標準庫中**文件結束判斷**的正確姿勢(feof/rewind),以及 UNIX 遺產、**DOS 3.0+ 支援**的非標準底層 I/O 函數族(open/close/read/write 等),頭文件 io.h。
feof:判斷文件結束的標準方式int feof(FILE *stream);
EOF (-1) 可能是合法數據位模式,單純檢查 fgetc() == EOF 會誤判。feof 區分「讀到 EOF 值」與「真正結束」。標準讀取循環模式:
while (!feof(fp)) {
int ch = fgetc(fp);
if (feof(fp)) break; // 雙重保險
process(ch);
}
rewind:歸零文件位置指示器int rewind(FILE *stream);
fseek(fp, 0, SEEK_SET) 但清除錯誤標誌)。源自 UNIX System V,io.h,DOS 3.0+ 支援。不經 FILE* 緩衝層,直接調用作業系統服務,適用於系統編程、高性能、特殊設備控制。
open:打開文件獲取描述符int open(char *filename, int access);
access = **基本模式** | **修飾符**(按位或 | 組合)。| 類別 | 常數 | 含義 |
|---|---|---|
| 基本模式 (三選一) | O_RDONLY | 只讀 |
O_WRONLY | 只寫 | |
O_RDWR | 讀寫 | |
| 修飾符 (可多選) | O_APPEND | 每次寫入前定位至文件末尾 |
O_CREAT | 文件不存在則創建(屬性依基本模式) | |
O_TRUNC | 文件存在則截斷長度為 0(屬性不變) | |
O_BINARY | 二進制模式 (無轉換) | |
O_TEXT | 文本模式 (換行符轉換) |
/* 讀寫二進制,不存在則創建,存在則截斷 */
int fd = open("data.bin", O_RDWR | O_BINARY | O_CREAT | O_TRUNC);
/* 只讀文本,追加寫入 */
int fd = open("log.txt", O_WRONLY | O_TEXT | O_APPEND);
close:關閉描述符int close(int fd);
| 函數 | 原型 | 功能 |
|---|---|---|
read | int read(int fd, void *buf, unsigned n) | 從 fd 讀最多 n 位元組到 buf,返回實際讀取位元組數 |
write | int write(int fd, const void *buf, unsigned n) | 向 fd 寫 buf 前 n 位元組,返回實際寫入位元組數 |
lseek | long lseek(int fd, long offset, int origin) | 移動 fd 位置指示器,origin: 0=SET, 1=CUR, 2=END |
tell | long tell(int fd) | 返回 fd 當前位置偏移量 |
eof | int eof(int fd) | 檢查 fd 是否到達文件末尾 |
| 維度 | 標準 I/O (FILE*) | 非標準 I/O (fd) |
|---|---|---|
| 可移植性 | ANSI C / ISO C 保證 | POSIX / UNIX / DOS 特定 |
| 緩衝 | 用戶態全缓冲/行緩衝/無緩衝 | 無用戶態緩衝,直達內核 |
| 格式化 | fprintf/fscanf 豐富 | 無,僅原始位元組 |
| 錯誤處理 | ferror/feof/perror | 返回值 + errno |
| 適用場景 | 應用層文本/二進制文件 | 系統編程、設備驅動、高吞吐、內存映射前置 |
fopen/fread/fwrite/fclose),可移植、功能豐富。open/read/write (POSIX) 或 CreateFile/ReadFile/WriteFile (Win32)。feof 解決二進制文件 EOF 判斷歧義,rewind 提供便捷歸零。非標準 I/O 以文件描述符為核心,access 位掩碼組合靈活強大,是系統級編程的利器。理解兩套體系的邊界與轉換,是從應用程序員進階為系統程序員的必修課。