C++的IO庫簡介
和文件有關系的輸入輸出類主要在fstream.h這個頭文件中被定義,在這個頭文件中主要被定義了三個類,由這三個類控制對文件的各種輸入輸出操 作,他們分別是ifstream、ofstream、fstream,其中fstream類是由iostream類派生而來,他們之間的繼承關系見下圖所 示。
由于文件設備并不像顯示器屏幕與鍵盤那樣是標準默認設備,所以它在fstream.h頭文件中是沒有像cout那樣預先定義的全局對象,所以我們必須自己定義一個該類的對象,我們要以文件作為設備向文件輸出信息(也就是向文件寫數據),那么就應該使用ofstream類。
ofstream類的默認構造函數原形為:
ofstream::ofstream(const char *filename,int mode = ios::out,int openprot = filebuf::openprot);
filename: 要打開的文件名
mode: 要打開文件的方式
prot: 打開文件的屬性
其中mode和openprot這兩個參數的可選項表見下表:
mode屬性表
ios::app: 以追加的方式打開文件
ios::ate: 文件打開后定位到文件尾,ios:app就包含有此屬性
ios::binary: 以二進制方式打開文件,缺省的方式是文本方式。兩種方式的區別見前文
ios::in: 文件以輸入方式打開
ios::out: 文件以輸出方式打開
ios::trunc: 如果文件存在,把文件長度設為0
可以用“或”把以上屬性連接起來,如ios::out|ios::binary。
openprot屬性表:
0:普通文件,打開訪問
1:只讀文件
2:隱含文件
4:系統文件
可以用“或”或者“+”把以上屬性連接起來 ,如3或1|2就是以只讀和隱含屬性打開文件。
示例代碼如下
#include <fstream> using namespace std; int main() { ofstream myfile("c://1.txt",ios::out|ios::trunc,0); myfile<<"U love C++"<<endl; myfile.close(); system("pause"); return 0; }
文件使用完后可以使用close成員函數關閉文件。
ofstream::app為追加模式,在使用追加模式的時候同時進行文件狀態的判斷是一個比較好的習慣。 如下面的代碼:
#include <iostream> #include <fstream> using namespace std; int main() { ofstream myfile("e://1.txt",ofstream::app); if(myfile.fail()) { cout << "文件創建失敗!"<<endl; exit(-1); } myfile << " Cobing" <<endl; myfile.close(); system("pause"); return 0; }
在定義ifstream和ofstream類對象的時候,我們也可以不指定文件。以后可以通過成員函數open()顯式的把一個文件連接到一個類對象上。如下例:
#include <iostream> #include <fstream> using namespace std; int main() { ofstream myfile; myfile.open("e://1.txt",ofstream::app); if(myfile.fail()) { cout << "文件創建失敗!"<<endl; exit(1); } myfile << "Cobing" <<endl; myfile.close(); system("pause"); return 0; }
下面我們來看一下是如何利用ifstream類對象,將文件中的數據讀取出來,然后再輸出到標準設備中的例子。
#include <iostream> #include <fstream> #include <string> using namespace std; int main() { ifstream myfile; myfile.open("e://1.txt",ifstream::in); if(myfile.fail()) { cout << "文件打開失敗!"<<endl; exit(1); } char ch; string content; while(myfile.get(ch)) { content+=ch; } myfile.close(); cout << content <<endl; system("pause"); return 0; }
我們利用成員函數get(),逐一的讀取文件中的有效字符,get()成員函數會在文件讀到默尾 的時候返回假值,所以我們可以利用它的這個特性作為while循環的終止條件,我們同時也在上例中引入了C++風格的字符串類型string,在循環讀取 的時候逐一保存到content中。
我們在簡單介紹過ofstream類和ifstream類后,我們再來看一下fstream類,fstream類是由iostream派生而來,fstream類對象可以同對文件進行讀寫操作。
#include <iostream> #include <fstream> using namespace std; int main() { fstream myfile; myfile.open("e://1.txt",fstream::out|fstream::app); if(myfile.fail()) { cout << "open failed!"<<endl; exit(1); } myfile << "cobing love C++" << endl; myfile.close(); myfile.open("e://1.txt",fstream::in); if(myfile.fail()) { cout << "open file failed!"<<endl; exit(1); } char ch; while(myfile.get(ch)) { cout << ch; } myfile.close(); system("pause"); return 0; }
由于fstream類可以對文件同時進行讀寫操作,所以對它的對象進行初始話的時候一定要顯式的指定mode和openprot參數。
接下來我們來學習一下串流類的基礎知識,什么叫串流類?
簡單的理解就是能夠控制字符串類型對象進行輸入輸出的類,C++不光可以支持C++風格的字符串流控制,還可以支持C風格的字符串流控制。
我們先看看看C++是如何對C風格的字符串流進行控制的,C中的字符串其實也就是字符數組,字符數組內的數據在內存中 的位置的排列是連續的,我們通常用char str[size]或者char *str的方式聲明創建C風格字符數組,為了能讓字符數組作為設備并提供輸入輸出操作,C++引入了ostrstream、istrstream、 strstream這三個類,要使用他們創建對象就必須包含strstream.h頭文件。
istrstream類用于執行C風格的串流的輸入操作,也就是以字符串數組作為輸入設備。
ostrstream類用于執行C風格的串流的輸出操作,也就是一字符串數組作為輸出設備。
strstream類同時可以支持C風格的串流的輸入輸出操作。
istrstream類是從istream(輸入流類)和strstreambase(字符串流基類)派生而來,ostrstream是從 ostream(輸出流類)和strstreambase(字符串流基類)派生而來,strstream則是從iostream(輸入輸出流類)和和 strstreambase(字符串流基類)派生而來。
串流同樣不是標準設備,不會有預先定義好的全局對象,所以不能直接操作,需要通過構造函數創建對象。
類istrstream的構造函數原形如下:
istrstream::istrstream(const char *str,int size);
參數1表示字符串數組,而參數2表示數組大小,當size為0時,表示istrstream類對象直接連接到由str所指向的內存空間并以/0結尾的字符串。
#include <iostream> #include <strstream> using namespace std; int main() { char *name = "key love c++"; int arraysize = strlen(name) + 1; istrstream istr(name,arraysize); char temp='.'; istr >> temp; system("pause"); return 0; }
類ostrstream用于執行C風格的串流的輸出,它的構造函數如下所示:
ostrstream::ostrstream(char *_Ptr,int streamsize,int Mode = ios::out);
第一個參數是字符數組,第二個是說明數組的大小,第三個參數是指打開方式。
接下來我們繼續看一下C++風格的串流控制,C++引入了ostringstream、istringstream、stringstream這三個類,要使用他們創建對象就必須包含sstream.h頭文件。
istringstream類用于執行C++風格的串流的輸入操作。
ostringstream類用于執行C++風格的串流的輸出操作。
stringstream類同時可以支持C++風格的串流的輸入輸出操作。
istringstream是由一個string對象構造而來,istringstream類從一個string對象讀取字符。
istringstream的構造函數原形如下:
istringstream::istringstream(string str);
#include <iostream> #include <sstream> using namespace std; int main() { istringstream is; is.str("k e y 1"); cout << is.str() <<endl; system("pause"); return 0; }
ostringstream的構造函數原形如下:
ostringstream::ostringstream(string str);
#include <iostream> #include <sstream> #include <string> using namespace std; int main() { ostringstream os; os.put('a'); os.put('b'); os << "ccde"; string str = os.str(); cout << str << endl; system("pause"); return 0; }
上例在控制臺輸出"abccde";
我們通過put()或者左移操作符可以不斷向ostr插入單個字符或者是字符串,通過str() 函數返回增長過后的完整字符串數據,但值得注意的一點是,當構造的時候對象內已經存在字符串數據的時候,那么增長操作的時候不會從結尾開始增加,而是修改 原有數據,超出的部分增長。
stringstream的構造函數原形如下:
stringstream::stringstream(string str);
stringstream類的對象我們還常用它進行string與各種內置類型數據之間的轉換。
#include <iostream> #include <sstream> #include <string> using namespace std; int main() { stringstream format_message; int val1=512, val2=1024; string init_str="/nwell done"; format_message << "val1:" << val1 << "/n" << "val2:" << val2; format_message << init_str; string get_message=format_message.str(); cout << get_message << endl; system("pause"); return 0; }
上例輸出:
val1:512
val2: 1024
well done
接下來我們來學習一下輸入/輸出的狀態標志的相關知識,C++中負責的輸入/輸出的系統包括了關于每一個輸入/輸出操作的結果的記錄信息。這些當前的狀態信息被包含在io_state類型的對象中。io_state是一個枚舉類型(就像open_mode一樣),以下便是它包含的值。
goodbit 無錯誤
eofbit 已到達文件尾
failbit 非致命的輸入/輸出錯誤,可挽回
badbit 致命的輸入/輸出錯誤,無法挽回
有兩種方法可以獲得輸入/輸出的狀態信息。一種方法是通過調用rdstate()函數,它將返回當前狀態的錯誤標記。例如,假如沒有任何錯誤,則rdstate()會返回goodbit.
#include <iostream> using namespace std; int main() { int a; cin >> a; cout << cin.rdstate() << endl; if(cin.rdstate()== istream::goodbit) { cout << "correct!"; } if(cin.rdstate() == istream::failbit) { cout << "failed!"; } system("pause"); return 0; }
上例輸出:0 correct!
另一種方法則是使用下面任何一個函數來檢測相應的輸入/輸出狀態:
bool bad();
bool eof();
bool fail();
bool good();
#include <iostream> using namespace std; int main() { int a; cin >> a; cout << cin.rdstate() << endl; if(cin.good()) { cout << "correct!"; } if(cin.fail()) { cout << "failed!"; } system("pause"); return 0; }
如果錯誤發生,那么流狀態既被標記為錯誤,你必須清除這些錯誤狀態,以使你的程序能正確適當地繼續運行。要清除錯誤狀態,需使用clear()函數。此函數帶一個參數,它是你將要設為當前狀態的標志值。,只要將stream::goodbit作為實參。
#include <iostream> #include <string> using namespace std; int main() { int a; cin >> a; cout << cin.rdstate() << endl; cin.setstate(iostream::failbit); cout << cin.rdstate() << endl; system("pause"); return 0; }
輸出:0 2 (其中goodbit為0,failbit為2)。