C++ I/O 採用流抽象,核心類繼承關係:
ios_base (格式狀態、區域設置)
↓
ios (關聯 streambuf)
↙ ↘
istream ostream (虛繼承 ios)
↓ ↓
iostream (多重繼承)
↓
fstream (文件流)
| 對象 | 類型 | 用途 | 緩衝特性 |
|---|---|---|---|
| `cin` | `istream` | 標準輸入 | 行緩衝 (遇 `\n` 刷新) |
| `cout` | `ostream` | 標準輸出 | 行緩衝 (交互) / 全緩衝 (重定向) |
| `cerr` | `ostream` | 標準錯誤 | 無緩衝 (立即輸出) |
| `clog` | `ostream` | 標準日誌 | 全緩衝 |
文件流操作詳解
打開模式組合
文本文件讀寫
二進制文件隨機訪問
(records), sizeof(records)); // 隨機讀取第 2 條記錄 (0-based) std::ifstream bin_in("records.dat", std::ios::binary); Record rec; bin_in.seekg(1 * sizeof(Record), std::ios::beg); // 定位 bin_in.read(reinterpret_cast(&rec), sizeof(Record)); // 修改第 1 條記錄 std::fstream bin_io("records.dat", std::ios::in | std::ios::out | std::ios::binary); bin_io.seekp(0 * sizeof(Record), std::ios::beg); records[0].score = 99.9; bin_io.write(reinterpret_cast (&records[0]), sizeof(Record)); // 獲取文件大小 bin_in.seekg(0, std::ios::end); std::streampos fsize = bin_in.tellg(); size_t count = fsize / sizeof(Record); 緩衝區深度解析
streambuf 核心角色
高級技巧與最佳實踐
1. 快速 I/O 優化
class Serializable { int id_; std::string name_; public: void save(std::ostream& os) const { os.write(reinterpret_cast(&id_), sizeof(id_)); size_t len = name_.size(); os.write(reinterpret_cast (&len), sizeof(len)); os.write(name_.data(), len); } void load(std::istream& is) { is.read(reinterpret_cast (&id_), sizeof(id_)); size_t len; is.read(reinterpret_cast (&len), sizeof(len)); name_.resize(len); is.read(&name_[0], len); } }; 3. 管道與進程間通信
4. 異常安全的文件操作
常見坑點總結
| 問題 | 原因 | 解決 |
|---|---|---|
| 二進制讀寫亂碼 | 文本模式下 `\n` ↔ `\r\n` 轉換 | 必須指定 `std::ios::binary` |
| `getline` 讀空行 | 前一次 `>>` 留下換行符 | `in.ignore()` 或統一用 `getline` |
| 數據未寫入磁盤 | 緩衝區未刷新/程序崩潰 | 關鍵數據用 `flush`、`sync_with_stdio(false)` 時手動刷新 |
| 隨機訪問定位錯誤 | 文本模式下位置非字節偏移 | 二進制模式 + `seekg/seekp` |
| 結構體對齊導致大小不一致 | 編譯器插入填充字節 | `#pragma pack(1)` 或手動序列化 |
C++ I/O 流體系以「流」為抽象核心,通過「流緩衝區」解耦設備細節。掌握:
理解「緩衝區是性能與正確性的平衡點」,在競程追求極速關閉同步,在工程追求穩健管理緩衝,是 C++ I/O 進階的分水嶺。