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

C 標準 I/O 深度解析:緩衝模式、檔案操作與二進制讀寫

     編輯:關於C語言

前言

C 標準 I/O 庫(stdio.h)提供跨平台、緩衝、格式化的檔案操作介面。深入理解其**三種緩衝模式**、**開檔模式語意**、**二進制讀寫限制**,能有效避免資料遺失、效能低落、跨平台亂碼等棘手問題。本文結合 APUE 經典內容與實戰經驗總結。

一、三種緩衝模式

模式觸發條件典型場景注意事項
全緩衝緩衝區滿 / fflush() / 正常程式結束磁碟檔案(預設)大量資料高效;異常終止可能丟失未刷新資料
行緩衝遇到 \n / 緩衝區滿 / 讀取無緩衝流 / fflush()標準輸入/輸出(終端互動)確保提示訊息即時顯示;重導向至檔案時變全緩衝
無緩衝每次 I/O 直接系統呼叫標準錯誤 stderr錯誤資訊即時輸出;效能最低

控制函數: setvbuf()、setbuf() 可在 fopen 後、首次 I/O 前切換模式與緩衝區大小。

二、檔案開啟模式詳解


FILE *fopen(const char *filename, const char *mode);
mode讀寫建立截斷定位備註
r✓開頭檔案必須存在
w✓✓✓開頭清空現有內容
a✓✓結尾追加寫入
r+✓✓開頭檔案必須存在
w+✓✓✓✓開頭清空現有內容
a+✓✓✓結尾讀可定位,寫永遠追加

二進制模式: 在 mode 字串中加入 b(如 "rb"、"wb+")。Windows 上區分換行符轉換(\n ⇄ \r\n),Linux/Unix 忽略 b。**跨平台處理二進制檔案務必加 b**。

三、讀寫切換關鍵規則

**當以讀寫模式開啟檔案(mode 含 +)時,輸出操作與輸入操作之間必須插入:fflush()、fseek()、fsetpos()、rewind() 其中之一。**

否則行為未定義(資料損壞、讀到舊資料、檔案位置錯亂)。

四、檔案關閉與程式結束

  • fclose(fp):刷新輸出緩衝、丟棄輸入緩衝、釋放結構體、釋放檔案描述符。
  • 正常結束(return 0/exit()):所有流自動刷新並關閉。
  • 異常結束(_exit()/abort()/信號終止):**不保證**刷新緩衝,關鍵資料須手動 fflush() 或用無緩衝流。

五、二進制 I/O: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);
  • 回傳**成功讀寫的物件數**(而非位元組數)。
  • 嚴重限制: 僅適用於**同一系統、同一編譯器、同一結構體定義**寫入的資料讀取。跨平台、跨語言、結構體記憶體對齊/位元組序差異會導致讀取錯誤。
  • 跨平台持久化請使用序列化格式(Protocol Buffers、MessagePack、JSON、自定義協議)。

六、常見坑點與對策

現象原因對策
printf 不顯示提示,scanf 卡住stdout 行緩衝,無 \n 未刷新fflush(stdout) 或 printf("...\\n")
重導向後輸出順序錯亂stdout 變全緩衝,stderr 仍無緩衝關鍵日誌用 stderr 或手動 fflush
二進制讀寫結構體跨平台錯誤記憶體對齊、大小端、填充位元組差異改用序列化庫
fgets 讀取最後一行無換行符檔案結尾無 \n檢查回傳值非 NULL 即有效
追加模式 fseek 失效a+ 模式寫入永遠在結尾改用 r+ 並手動 fseek 到末尾

七、現代替代方案

  • C++: <fstream>(RAII)、<filesystem> (C++17)、fmt 庫(格式化)。
  • 高效能: mmap、io_uring (Linux)、記憶體映射檔案。
  • 跨平台: boost::iostreams、libuv 非同步 I/O。

總結

C 標準 I/O 以「緩衝 + 格式化 + 跨平台」三大特性橫跨四十年仍是系統程式基石。掌握**緩衝模式選擇**、**讀寫切換屏障**、**二進制 I/O 侷限性**,並養成「關鍵點 fflush、錯誤走 stderr、持久化用序列化」的工程習慣,即能駕馭絕大多數檔案操作場景。

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