C++標準IO庫
概述
先不要急著知道怎麽用這個玩意,讓我們一起先來看一看C++標準IO庫的框架,其實挺有意思的!那就開始吧!
C++的輸入輸出由標準庫提供,標準庫提供了一族類型,支持對文件、string對象、和控制窗口等設備的讀寫。一方面,這些IO類型都定義了如何讀寫內置類型的的值,另一方面,用戶在設計類時可以仿照IO標準庫設施讀寫內置類型的方式設計自己的輸入輸出操作。
1. 面向對象的IO庫
面向對象是C++的一大特色,他的標準庫自然也不例外,統統都是面向對象設計的。標準庫使用了繼承(inheritance)來定義一組面向對象(object-oriented)類。IO類型定義在三個獨立的頭文件中:iostream定義讀寫控制窗口的類型;fstream定義讀寫已命名文件的類型;sstream定義讀寫存儲在內存中的string對象的類型。各頭文件包含的類型及其含義以及各類型之間的繼承關系如下圖:
註意:
- 以上所講的流類型(stream class)讀寫的是由char類型組成的流。除此之外,標準庫還定義了一組相關的類型,支持wchar_t類型。即,每個類名前都加上“w”前綴,以此與char類型的版本區別開來。
- IO對象不允許復制和賦值:因此流對象不可以存儲在vector或其他容器裏;函數形參和返回類型也不可以是流類型。
2. 標準IO庫定義的------條件狀態
標準IO 庫管理一系列條件狀態(condition state)成員,用來標記給定的 IO 對象是否處於可用狀態,或者碰到了哪種特定的錯誤。如下列出了標準庫定義的一組函數和標記,提供訪問和操縱流狀態的手段。
strm::iostate 這是機器相關的整型別名,代表一種類型,由各個io類定義,用於定義條件狀態(strm在這裏代表各個流類型)。
strm::badbit strm::iostate類型的值,用於指出被破壞的流。
strm::failbit strm::iostate類型的值,用於指出失敗的 IO 操作。
strm::eofbit strm::iostate類型的值,用於指出流已經到達文件結束符。
s.eof() 返回eof標誌位的值,真或假。
s.fail() 返回fail標誌位的值,真或假。
s.bad() 返回bad標誌位的值,真或假。
s.good() 檢測流s的有效性,當eof,fail,bad都不為真時good標誌位有效,調用good()函數返回真值。
s.clear() 將流s中的所有狀態值都重設為有效狀態。
s.clear(flag) 將流s中的某個指定條件狀態置為有效,flag是strm::iostate類型的條件狀態,若括號內不寫具體條件狀態則將所有條件狀態全部設置有效。
s.setstate(flag) 給流添加指定條件,設置flag位為觸發狀態,flag是strm::iostate類型對象。
s.rdstate() 返回流s的當前條件,返回值類型為strm::iostate。
總結-----條件狀態:
- 所有流對象都包含一個條件狀態成員,他是strm::iostate類型的對象,以二進制位的形式使用。
- failbit, eofbit, badbit和goodbit是四個strm::iostate類型的常量值,他們本身分別表示一種條件狀態,具體如下表:
常量 含義 fail標誌位 oef標誌位 bad標誌位 ios::badbit 輸入(輸出)流出現致命錯誤,不可挽回 0 0 1 ios::eofbit 已達到文件結束 0 1 0 ios::failbit 輸入(輸出)流出現非致命錯誤,可挽回 1 0 0 ios::goodbit 流狀態完全正常 0 0 0
- badbit, eofbit, failbit,goodbit構成了四個基本流狀態。
- 用cout檢測goodbit, badbit, eofbit, failbit的值分別是0,1,2,4,這與上面的表格不是正好完全對應著嗎,呵呵(goodbit:0000 0000; badbit:0000 0001;eofbit:0000 0010; failbit:0000 0100)。
- 可使用clear和setstate來操作和管理條件狀態成員,他們常與badbit,eofbit,failbit,goodbit以及位或“|”結合起來使用。
- 用bad(), fail(), eof()和good()操作可以檢測流狀態是否屬於,還可以用rdstate()來返回整個條件狀態成員。
2.1 rdstate的使用:
rdstate成員函數返回一個iostate類型的值,前面已經說過,這是一個與機器相關的整型,該值對應於流的整個條件狀態。如下代碼:(摘自cplusplus.com)
// getting state of stream object
#include <iostream>
#include <fstream>
using namespace std;
int main ()
{
ifstream is;
is.open ("test.txt");
if ( (is.rdstate() & ifstream::failbit ) != 0 ) //檢測fail標誌位是否被設置,即是否遇到錯誤
cerr << "Error opening ‘test.txt‘\n"; return 0;
}
2.2 clear的使用:
clear用於設置標誌位而不是清除標誌位,即按照實參設置流狀態,強制覆蓋原有狀態,其工作方式有兩種:
- 帶有failbit, eofbit, badbit,goodbit中的一個或多個作為參數,按照具體實參設置流對象,例如goodbit作實參時就設置流狀態各位為0。
- 不帶參數,即默認狀態,效果如同帶goodbit作為參數,會將所有標誌位設置為有效。
// clearing errors #include <iostream> #include <fstream> using namespace std; int main () { char buffer [80]; fstream myfile; myfile.open ("test.txt",fstream::in); myfile << "test"; if (myfile.fail()) { cout << "Error writing to test.txt\n"; myfile.clear(); } myfile.getline (buffer,80); cout << buffer << " successfully read from file.\n"; return 0; }
2.3 setstate的使用:
setstate用於設置標誌位狀態,與clear的區別在於它只是在原有狀態的基礎上以疊加的方式更新實參對應狀態標誌,而不會強制覆蓋原有狀態,使用方式:
- 傳遞一個strm::iosatate類型的參數(可以是單個的,也可以是用“位或”連接的多個iostate對象)
3. 輸出緩沖區的管理-----關鍵在於控制如何刷新緩沖區
每一個IO對象管理一個緩沖區,用於存儲程序讀寫的數據。緩沖區的刷新會使其中的內容寫入到真實的輸出設備或文件中。以下情況都會導致緩沖區被刷新:
- 程序正常結速時,將清空所有輸出緩沖區。
- 在一些不確定的時候,緩沖區可能已經滿了,這種情況下,緩沖區將會在寫入下一個值之前刷新緩沖區。
- 用操縱符(endl, ends,flush)顯式地刷新緩沖區:
cout<<"Hi!"<<endl; //插入換行符,並刷新緩沖區
cout<<"Hi!"<<ends; //插入空格字符null,並刷新緩沖區
cout<<"Hi!"<<flush; //僅僅刷新緩沖區,不插入任何其他字符
- 用unitbuf操縱符設置流的內部狀態,使得流在每次輸出操作執行完都清空緩沖區,恢復系統默認管理方式用nounitbuf。
cout<<unitbuf<<"first"<<"second"<<"third"<<nounitbuf; //等價於cout<<"first"<<flush<<"second"<<flush<<"third"<<flush;
- 使用tie函數將輸出流與輸入流關聯起來,當輸入流與輸出流綁定在一起的時候,任何輸入操作都將首先刷新其輸出流關聯的緩沖區。
補充------------tie函數的使用:
tie函數可以由istream或ostream對象調用,使用一個ostream流對象的指針做形參。
- cin.tie(&cout);//將cin和cout綁定在一起,cin>>ival;時將導致cout所關聯的緩沖區被刷新。
- ostream *old_tie=cin.tie(); //不傳遞參數時,返回當前綁定的對象
- cin.tie(0); 接受0作為參數時,解除當前綁定
本文只作為C++標準IO庫的基礎概括,文件、string對象、和控制窗口的具體IO操作方法,將另外撰文,鏈接如下:
C++中的文件輸入輸出:http://blog.csdn.net/miss_acha/article/details/7194695
C++標準IO庫