很多人在C++編程中習慣使用ANSI C下的檔案類型指標FILE來執行檔案的有關操作,這難免影響C++程式的總體美觀性。另外,C++標準IO庫中提供了更為完善、易用的檔案操作方法,所以建議使用標準庫來實現檔案的輸入/輸出,培養一種好的編程習慣。
1.檔案的輸入輸出
檔案操作的標頭檔有:ifstream提供檔案讀取功能;ofstream提供檔案寫入功能;fstream提供檔案的讀寫功能(包括了前兩類的功能,實現對同一檔案的讀寫雙操作)。
a.定義對象
ifstream infile; //定義輸入對象ofstream outfile; //定義輸出對象
b.在使用fstream對象之前,還必須使這些對象綁定要讀寫的檔案
infile.open ("in.txt"); //要輸入in.txt檔案outfile.open ("out.txt"); //要輸出out.txt檔案
當然,fstream類提供了建構函式,可以在定義對象時初始化實現上述兩步
ifstream infile ("in.txt"); //定義infile對象,輸入in.txt檔案內容ofstream outfile ("out.txt"); //定義outfile對象,輸出內容到out.txt檔案
c.檢查檔案開啟是否成功
if (!infile){ cout << "error: unable to open the file" << endl; return -1;}
d.檔案內容的處理
I.成員函數eof()用來檢測是否到達檔案尾,如果到達檔案尾返回非0值,否則返回0
//輸入檔案,進行處理時使用if (!infile.eof()){ process();}
II.檔案分為文字檔和二進位檔案,對文字檔的處理比較簡單,用插入器和析取器就可以了;而對於二進位的處理要複雜些,下要分別介紹這兩種方式
文字檔:用插入器(<<)向檔案輸出;用析取器(>>)從檔案輸入。假設infile以輸入方式開啟,outfile以輸出開啟
outfile<<"向檔案輸出";string word;infile>>word; //檔案內容輸入到word,word是檔案中某個字串
這種方式還有一種簡單的格式化能力,比如可以指定輸出為16進位等等
操縱符 |
功能 |
輸入/輸出 |
dec |
格式化為十進位數值資料 |
輸入和輸出 |
hex |
格式化為十六進位數值資料 |
輸入和輸出 |
oct |
格式化為八位元值資料 |
輸入和輸出 |
setpxecision(int p) |
設定浮點數的精度位元 |
輸出 |
endl |
輸出一個分行符號並重新整理此流 |
輸出 |
ends |
輸出一個Null 字元 |
輸出 |
比如要把123當作十六進位輸出:outfile<<hex<<123;要把3.1415926以5位精度輸出:outfile<<setpxecision(5)<<3.1415926
getline函數,輸入檔案的一行,函數原型
istream& getline (istream& is, string& str, char delim);istream& getline (istream& is, string& str);
從 is 中讀取字串存入 str 中,直到遇到分隔字元delim為止。對於第二種形式,getline遇到 '\n’ 停止。執行過程中,如果delim出現,它會被讀取並丟棄,下次輸入將在它之後開始。
二進位檔案:put()函數向流寫入一個字元,其原型是ofstream &put(char ch),使用也比較簡單,如outfile.put('c');就是向流寫一個字元'c'。
get()函數比較靈活,有3種常用的重載形式:
一種就是和put()對應的形式:ifstream &get(char &ch);功能是從流中讀取一個字元,結果儲存在引用ch中,如果到檔案尾,返回Null 字元。如infile.get(x);表示從檔案中讀取一個字元,並把讀取的字元儲存在x中。
另一種重載形式的原型是: int get();這種形式是從流中返回一個字元,如果到達檔案尾,返回EOF,如x=file2.get();和上例功能是一樣的。
還有一種形式的原型是:ifstream &get(char *buf,int num,char delim=' ');這種形式把字元讀入由 buf 指向的數組,直到讀入了 num 個字元或遇到了由 delim 指定的字元,如果沒使用 delim 這個參數,將使用預設值分行符號' '。
讀寫位元據塊,要使用成員函數read()和write()成員函數,它們原型如下:
read (unsigned char *buf, int num);write (const unsigned char *buf, int num);
III.檔案的定位,C++的檔案定位分為讀位置和寫位置的定位,對應的成員函數是 seekg()和 seekp(),seekg()是設定讀位置,seekp是設定寫位置。它們最通用的形式如下:
istream &seekg (streamoff offset, seek_dir origin);ostream &seekp (streamoff offset, seek_dir origin);
offset定義了位移量,seek_dir 表示移動的基準位置,是一個有以下值的枚舉:
ios::beg: 檔案開頭
ios::cur: 檔案當前位置
ios::end: 檔案結尾
這兩個函數一般用於二進位檔案(位元組),因為文字檔會因為系統對字元的解釋而可能與預想的值不同。
file1.seekg (1234,ios::cur); //把檔案的讀指標從當前位置向後移1234個位元組file2.seekp (1234,ios::beg); //把檔案的寫指標從檔案開頭向後移1234個位元組
e.檔案關閉
程式結束或fstream對象與另一檔案關聯時,必須先關閉現在的檔案。
infile.close(); //關閉infile檔案
2.檔案模式
在開啟檔案時,無論是調用open還是以檔案名稱作為流初始化的一部分,都需要指定檔案模式。檔案流建構函式和open函數都提供了預設參數來設定檔案模式,預設值因流類型的不同而不同。常用的檔案模式與含義如下:
檔案模式 |
含義 |
in |
開啟檔案作讀操作 |
out |
開啟檔案作寫操作 |
app |
在每次寫之前找到檔案尾 |
ate |
開啟檔案時把檔案定位在檔案尾 |
trunc |
開啟檔案時清空已存在的檔案流 |
binary |
以二進位模式進行IO操作 |
以binary模式開啟的流將檔案以位元組序列的形式處理,而不解釋流中的字元。
預設情況下,與ifstream流對相關聯的檔案以in模式開啟,與ofstream關聯檔案以out模式開啟。以out模式開啟的檔案會被清空,丟棄該檔案儲存體的所有資料,從效果來看,為ofstream對象指定out模式等效於指定了out和trunc模式。
模式的組合,多個檔案模式可以同時指定,但是有些組合是沒有意義的,常見的組合模式如下
組合模式 |
含義 |
out | app |
開啟檔案做寫操作,檔案尾寫入 |
out | trunc |
開啟檔案做寫操作,刪除檔案已有資料(與out相同) |
in | out |
開啟檔案做讀、寫操作,定位到檔案開頭處 |
in | out | trunc |
開啟檔案做讀、寫操作,刪除檔案中已有資料 |
in | out | ate |
開啟檔案做讀、寫操作,定位到檔案末尾處 |
…… |
…… |