傳統 C 風格文件 I/O(<stdio.h> 的 fopen/fread、Unix <io.h> 的 open/read)介面偏向底層,強迫程式設計師手動管理緩衝區、型別轉換,且缺乏型別安全與國際化支援。C++ 標準庫 <fstream> 提供物件導向、型別安全、具備國際化意識的高層抽象,並能輕易撰寫跨平台程式碼。
std::ifstream:輸入檔案流,支援 operator>> 讀取。std::ofstream:輸出檔案流,支援 operator<< 寫入。std::fstream:同時支援讀寫的檔案流。std::ios_base 與 std::ios,擁有完善的狀態旗標與格式化控制。注意:舊版 <fstream.h> 已棄用,新標準 <fstream> 不再支援 ios::nocreate、ios::noreplace 旗標。
#include <iostream>
#include <string>
#include <fstream>
#include <cstdlib>
using namespace std;
int main()
{
string filename;
cout << "enter dictionary file: ";
cin >> filename;
// 建構子直接嘗試開啟檔案,需轉為 C 風格字串
ifstream dict(filename.c_str());
if (!dict) // 以 operator! 檢查開檔是否失敗
{
cerr << "Cannot open file." << endl;
return -1;
}
string word;
while (dict >> word) // operator>> 自動處理 EOF
cout << word << '\n';
// 無需手動 close(),解構函數會自動關閉
return 0;
}
可用位元或 | 組合:
ios::in:讀取模式(ifstream 預設)。ios::out:寫入模式(ofstream 預設)。ios::app:附加模式,寫入位置永遠在檔案末尾。ios::ate:開啟後立即移至檔案末尾。ios::binary:二進位模式(預設為文字模式)。ios::trunc:截斷檔案長度為零。// 二進位附加寫入
ofstream logfile("login.dat", ios::binary | ios::app);
// 同時讀寫
fstream db("database.dat", ios::in | ios::out);
seekp(pos):移動寫入指標至絕對位移(位元組)。seekp(offset, origin):相對移動,origin 可為 ios::beg(檔案開頭)、ios::cur(目前位置)、ios::end(檔案結尾)。tellp():取得目前寫入指標位置。seekg/tellg。ofstream fout("parts.txt");
fout.seekp(10); // 從開頭偏移 10 位元組
cout << "new position: " << fout.tellp(); // 輸出 10
fout.seekp(5, ios::cur); // 從目前位置再前進 5
fout.seekp(-10, ios::end); // 從檔尾倒退 10
<< 與 >> 運算子已為所有內建型別、std::string、std::complex 等多載:
fstream log("log.dat");
log << time(0) << "danny" << '\n'; // 寫入時間戳記與字串
log.seekg(0, ios::beg); // 重置讀取指標
time_t t; string user;
log >> t >> user; // 讀回
rdstate()、good()、eof()、fail()、bad() 檢查流狀態。clear() 重置錯誤旗標。setf()、unsetf()、precision()、width()、fill() 控制輸出格式。imbue(locale) 支援國際化數字/貨幣格式。Danny Kalev,認證系統分析師與軟體工程師,專精 C++ 與形式語言理論。1997-2000 年任 C++ 標準委員會成員。碩士論文研究普通語言學。業餘喜好古典音樂、維多利亞文學、自然語言研究(Hittite、Basque、Irish Gaelic)、考古與地理。常活躍於 C++ 論壇,定期為技術網站與雜誌撰稿,並授課程式語言課程。
<fstream> 以 RAII 管理資源、型別安全的運算子多載、靈活的定位與格式化機制,成為現代 C++ 檔案 I/O 的首選。善用它能寫出更健壯、可維護、跨平台的程式碼。
本文配套原始碼可供下載。