部分內容轉載:http://blog.csdn.net/kingstar158/article/details/6859379 感謝追求執着,原本想自己寫,卻發現了這么明白的文章。
C++文件流操作是基礎內容之一,但是內容繁雜,其實會者不難,這里簡單概述一下:
需要調用的類:
#include<fstream>
讀入/輸出有兩種方法,第一種是流的方法。
讀入:
ifstream file("InterestSettings.dat"); if (file) { while (!file.eof()) { file >> alive >> threemonth >> halfyear >> oneyear >> twoyear >> threeyear >fiveyear; } } file.close();
輸出:
ofstream file("InterestSettings.dat"); if (file) { file << alive << threemonth << halfyear << oneyear << twoyear << threeyear << fiveyear; } file.close();
上述代碼中file.eof()表示文件到結尾。
一些驗證流的狀態的成員函數(所有都返回bool型返回值):
- bad()如果在讀寫過程中出錯,返回 true 。例如:當我們要對一個不是打開為寫狀態的文件進行寫入時,或者我們要寫入的設備沒有剩余空間的時候。
- fail()除了與bad() 同樣的情況下會返回 true 以外,加上格式錯誤時也返回true ,例如當想要讀入一個整數,而獲得了一個字母的時候。
- eof()如果讀文件到達文件末尾,返回true。
- good()這是最通用的:如果調用以上任何一個函數返回true 的話,此函數返回 false 。
要想重置以上成員函數所檢查的狀態標志,你可以使用成員函數clear(),沒有參數。
ifstream 默認以ios::in的方式來進行文件的讀取,也可以表述成:
fstream file("File.dat",ios::in)
關於ios::in,這是一個開關,C++ 文件操作一共有以下開關
ios::in | 為輸入(讀)而打開文件 |
ios::out | 為輸出(寫)而打開文件 |
ios::ate | 初始位置:文件尾 |
ios::app | 所有輸出附加在文件末尾 |
ios::trunc | 如果文件已存在則先刪除該文件 |
ios::binary | 二進制方式 |
這些方式是能夠進行組合使用的,以“或”運算(“|”)的方式:例如
fstream DeadAccountFile("DeadAccount.dat", ios::in | ios::out | ios::binary);
除了在構造器中打開文件,也可使用.open()函數,上述代碼可以改成:
fstream DeadAccountFile; DeadAccountFile.open("DeadAccount.dat", ios::in | ios::out | ios::binary);
同理,文件使用結束時,要使用.close()函數使文件關閉
fstream setup("DeadAccount.dat", ios::out); setup.close();
獲得和設置流指針
我們可以通過使用以下成員函數來讀出或配置這些指向流中讀寫位置的流指針:
tellg() 和 tellp()
這兩個成員函數不用傳入參數,返回pos_type 類型的值(根據ANSI-C++ 標准) ,就是一個整數,代表當前get 流指針的位置 (用tellg) 或 put 流指針的位置(用tellp).
seekg() 和seekp()
這對函數分別用來改變流指針get 和put的位置。兩個函數都被重載為兩種不同的原型:
seekg ( pos_type position );
seekp ( pos_type position );
使用這個原型,流指針被改變為指向從文件開始計算的一個絕對位置。要求傳入的參數類型與函數 tellg 和tellp 的返回值類型相同。
seekg ( off_type offset, seekdir direction );
seekp ( off_type offset, seekdir direction );
使用這個原型可以指定由參數direction決定的一個具體的指針開始計算的一個位移(offset)。它可以是:
ios::beg | 從流開始位置計算的位移 |
ios::cur | 從流指針當前位置開始計算的位移 |
ios::end | 從流末尾處開始計算的位移 |
流指針 get 和 put 的值對文本文件(text file)和二進制文件(binary file)的計算方法都是不同的,因為文本模式的文件中某些特殊字符可能被修改。由於這個原因,建議對以文本文件模式打開的文件總是使用seekg 和 seekp的第一種原型,而且不要對tellg 或 tellp 的返回值進行修改。對二進制文件,你可以任意使用這些函數,應該不會有任何意外的行為產生。
在二進制文件中,使用<< 和>>,以及函數(如getline)來操作符輸入和輸出數據,沒有什么實際意義,雖然它們是符合語法的。文件流包括兩個為順序讀寫數據特殊設計的成員函數:write 和 read。第一個函數 (write) 是ostream 的一個成員函數,都是被ofstream所繼承。而read 是istream 的一個成員函數,被ifstream 所繼承。類 fstream 的對象同時擁有這兩個函數。它們的原型是:
write ( char * buffer, streamsize size );
read ( char * buffer, streamsize size );
接下來我來舉例說明:
輸出:
fstream DeadAccountFile("DeadAccount.dat", ios::in | ios::out | ios::binary); if (!DeadAccountFile) { cerr << "DataBase could not open" << endl; exit(0); } for (int i = 0; i < (int)DeadAccountArray.size(); i++) { DeadAccountFile.seekp(i*sizeof(DeadAccount)); DeadAccountFile.write(reinterpret_cast<const char*>(&DeadAccountArray[i]), sizeof(DeadAccount)); }
輸入:
fstream readfile("SavingAccount.dat", ios::in | ios::out | ios::binary); if (!readfile) { cerr << "DataBase could not open" << endl; exit(0); } SavingAccount SavingAccountTemp; SavingAccountArray.clear(); for (int i = 0; !readfile.eof(); i++) { readfile.seekg(i*sizeof(SavingAccount)); readfile.read(reinterpret_cast<char*>(&SavingAccountTemp), sizeof(SavingAccount)); SavingAccountTemp.setinterest(alive); SavingAccountArray.push_back(SavingAccountTemp); }