用戶使用 ios::ate 打開文件期望追加寫入,但內容仍被覆蓋。並詢問 ofstream 與 fstream 的區別。
| 標志 | 含義 | 是否追加 | 是否截斷 |
|---|---|---|---|
ios::app | 每次寫入前定位到文件末尾 | ✅ 是 | ❌ 否 |
ios::ate | 打開後立即定位到文件末尾 | ❌ 否(後續寫入仍從當前位置) | ❌ 否 |
ios::out | 輸出模式 | — | ✅ 是(默認截斷) |
ios::trunc | 截斷文件 | — | ✅ 是 |
結論:要追加寫入必須包含 ios::app。ios::ate 僅控制初始位置,不保證後續寫入在末尾。
#include <fstream>
#include <string>
using namespace std;
int main() {
// 方式 1:ofstream 專用輸出,追加模式
ofstream ofs("同學錄系統.txt", ios::app | ios::out);
if (!ofs) {
cerr << "文件打開失敗" << endl;
return 1;
}
ofs << "新記錄: 張三, 20, CS\n";
ofs.close(); // RAII 析構自動關閉,顯式 close 也可
// 方式 2:fstream 讀寫雙向,追加模式
fstream fs("同學錄系統.txt", ios::app | ios::out | ios::in);
if (fs) {
fs << "另一條: 李四, 22, Math\n";
// 也可讀取
fs.seekg(0, ios::beg);
string line;
while (getline(fs, line)) cout << line << endl;
}
return 0;
}
ofstream vs fstream 區別| 特性 | ofstream | fstream |
|---|---|---|
| 繼承關係 | ostream → ios | iostream → istream + ostream |
| 默認模式 | ios::out | ios::in | ios::out |
| 適用場景 | 純寫入/追加(日誌、導出) | 需同時讀寫(修改現有文件、隨機訪問) |
| 隨機訪問 | 僅 seekp (寫位置) | seekg (讀) + seekp (寫) |
ios::ate 等於追加:錯!ate 只在打開時跳到末尾,後續 << 仍從當前位置寫,若未移動指針會覆蓋末尾數據。if (!ofs) 判斷。\n 寫入文本流會自動轉 \r\n,二進制模式 ios::binary 則不轉換。flock、mutex),流本身不保證原子性。ofstream file("log.txt", ios::app);fstream file("data.txt", ios::in | ios::out | ios::app); 注意 app 會強制寫入末尾,seekp 失效;若需隨機寫入請去掉 app 手動 seekp。close() 並刷新緩衝區。追加寫入的「金鑰」是 ios::app。ofstream 專職專用,fstream 雙向靈活。記住模式標志組合邏輯,配合狀態檢查,文件操作不再踩坑。