IO庫
1 IO類
常用的IO庫類型和頭文件如下表:
頭文件 | 類型 |
---|---|
iostream |
istream ,wistream 從流讀取數據 |
ostream ,wostream 向流寫入數據 |
|
iostream ,wiostream 讀寫流 |
|
fstream |
ifstream ,wifstream 從文件讀取數據 |
ostream ,wofstream 向文件寫入數據 |
|
fstream ,wfstream 讀寫文件 |
|
sstream |
istringstream ,wistringstream 從string讀取數據 |
ostringstream ,wostringstream 向string寫入數據 |
|
stringstream ,wstringstream 讀寫string |
w開頭的表示寬字符類型
1.1 條件狀態
名稱 | 描述 |
---|---|
strm::iostate |
strm 是一種IO類型,在上表中已列出 |
strm::badbit |
用來指出流已經崩潰 |
strm::failbit |
用來指出一個IO操作失敗了 |
strm::eofbit |
用來指出流到達了文件結束 |
strm::goodbit |
用來指出流未處於錯誤狀態 |
s.eof() |
若流s的eofbit 置位,則返回true |
s.fail() |
若流s的failbit 或badbit 置位,則返回true |
s.bad() |
若流s的badbit 置位,則返回true |
s.good() |
若流s處於有效狀態,則返回true |
s.clear() |
將流s中所有條件狀態復位,將流的狀態設置爲有效。返回void |
s.clear(flags) |
根據給定的flag標誌位,將流s中對應條件狀態位復位。flag類型爲strm::iostate |
s.setstate(flags) |
根據給定的flag標誌位,將流s中對應條件狀態位置位。flag類型爲strm::iostate |
s.rdstate() |
返回流s的當前條件狀態,返回類型爲strm::iostate |
1.2 管理輸出緩衝
每一個輸出流都管理一個緩衝區,用來保存程序讀寫的數據。其中導致緩衝區刷新的原因有如下幾種:
- 程序正常結束
- 緩衝區滿時,需要刷新緩衝區,後面新來的數據才能繼續寫入緩衝區
- 使用操作符如endl來顯示刷新緩衝
- 在每個輸出操作之後,可以用操作符unitbuf設置流的內部狀態,來清空緩衝區
- 一個輸出流可能被關聯到另一個流,當讀寫被關聯的流時,關聯到的流的緩衝區會被刷新
刷新輸出緩衝區操作符:flush和ends,其中flush刷新緩衝區,但不輸出任何額外的字符;ends向緩衝區插入一個空字符,然後刷新緩衝區。
2 文件輸入輸出
頭文件fstream
定義了三個類型來支持文件IO:ifstream
從一個給定文件讀取數據,ofstream
向一個給定文件寫入數據,fstream
可以讀寫給定文件
名稱 | 描述 |
---|---|
fstream fstrm; |
創建一個未綁定的文件流 |
fstream fstrm(s); |
創建一個fstream ,並打開名爲s的文件,s可以是string類型,或指向C風格字符串的指針 |
fstream fstrm(s, mode); |
創建一個fstream ,並打開名爲s的文件,按指定mode打開文件 |
fstrm.open(); |
打開名爲s的文件,並將文件與fstrm 綁定 |
fstrm.close(); |
關閉與fstrm 綁定的文件。返回void |
fstrm.is_open(); |
返回一個bool 值,表示與fstrm 關聯的文件是否打開成功並且尚未關閉 |
示例:
ifstream in(ifile); //創建一個ifstream並打開給定文件
ofstream out; //輸出文件流
out.open(ifile + ".txt"); //打開指定文件
2.1 文件模式
操作 | 描述 |
---|---|
in |
以讀方式打開文件 |
out |
以寫方式打開文件 |
app |
每次寫操作前均定位到文件末尾 |
ate |
打開文件後立即定位到文件末尾 |
trunc |
截斷文件 |
binary |
以二進制方式進行IO |
指定文件模式有如下限制:
- 只可以對
ofstream
或fstream
對象設定out模式 - 只可以對
ifstream
或fstream
對象設定in模式 - 只有當out也被設定時,纔可設定trunc模式
- ate和binary模式可用於任何類型的文件流對象,且可以與其他任何文件模式組合使用
- 只要trunc沒有被設定。就可以設定app模式。在app模式下即使沒有顯式指定out模式,文件也總是以輸出方式被打開。
- 即使沒有指定trunc,以out模式打開的文件也會被截斷,因此爲保留此時的內容,必須同時指定app模式,這樣數據將追加寫到文件末尾
Tips:當打開一個ofstream
時文件的內容會被丟棄,因此此時必須顯式指定app或in模式
示例如下:
//文件內容會被截斷
ofstream app("file2");
ofstream app("file2", ofstream::out);
//文件內容保留
ofstream app("file2", ofstream::app);
ofstream app("file2", ofstream::out | ofstream::app);
3 string流
名稱 | 描述 |
---|---|
sstream strm; |
strm 是一個未綁定的stringstream 對象。sstream 是頭文件sstream 中定義的一個類型 |
sstream strm(s); |
strm 是一個sstream 對象,保存string s 的一個拷貝 |
strm.str() |
返回strm 所保存的string的拷貝 |
strm.str(s) |
將string s 拷貝到strm 中,返回void |
3.1 使用istringstream
示例如下:
現有一個這樣的文件,其輸入格式如下:
morgan 2015552368 8625550123
drew 9735550130
lee 6095550132 2015550175 8005550000
首先定義一個簡單的類來描述輸入數據:
struct PersonInfo{
string name;
vector<string> phones;
}
讀取信息的實例函數如下:
string line,word; //分別保存來自輸入的一行和單詞
vector<PersonInfo> people; //保存來自輸入的所有記錄
while (getline(cin, line)){ //逐行從輸入讀取數據,直到遇到文件末尾
PersonInfo info; //創建一個保存此記錄數據的對象
istringstream record(line); //將記錄綁定到剛讀入的行
record >> info.name; //讀取名字
while(record >> word) //讀取電話號碼
{
info.phones.push_back(word);//保持它們
}
people.push_back(info); //將此記錄追加到people末尾
}
這裏的istringstream
將getline
讀取的文本進行綁定,然後在istringstream
上使用輸入運算符來讀取當前記錄中的每個元素,即元素之間以空格爲區分。
3.2 使用ostringstream
對於上例,現將每個人的電話打印出來,但是不希望輸出無效電話號碼的人,因此需要進行驗證。此時可以先將要輸出的內容“寫入”到一個內存ostringstream
中,其代碼如下:
for(const auto &entry : people) //對people中的每一項
{
ostringstream formatted,badNums; //每個循環步創建的對象
for(const auto &num : entry.phones) //對每個數
{
if(!valid(nums))
{
badNums << " " << nums; //將數的字符串形式存入badNums
}
else
formatted << " " << format(num); //將格式化的字符串“寫入”formatted
}
if(bad.Nums.str().empty()) //沒有錯誤的數
//打印名字和格式化的數
os << entry.name << " " << formatted.str() << endl;
else//打印名字和錯誤的數
ceer << "input error: " << entry.name
<< " invalid number(s)" << badNums.str() << endl;
}