C++的I/O流體系ios
繼承關係:數組
ios <-- istream/ostreamapp
|--> istream <-- istrstream/ifstream/iostreamide
|--> ostream <-- ostrstream/ofstream/iostream函數
|--> iostream <-- strstream/fstreamspa
istream及其子類支持輸入操做對象
ostream及其子類支持輸出操做繼承
由istream和ostream共同派生的子類iostream既支持輸入也支持輸出。ip
1.經過ofstream類單參(文件路徑)構造函數能夠打開一個文件用於向文件中輸出,若是文件不存在,該類的構造函數將以缺省的方式建立文件;內存
若是文件存在,進行覆蓋
2.ofstream的兩參數(文件路徑,打開模式openmode)版本
ios::in:打開文件用於從文件中讀取
ios::out:打開文件用於向文件中寫入
ios::app:打開文件用於向文件中追加
ios::ate:打開文件,把文件位置設置到文件尾部,用於從文件讀取
// 在打開文件流時使用ios::ate選項,將文件的get位置置於文件尾
ifstream ifs ("文件路徑", ios::binary | ios::ate);
if (! ifs)
PrintError (__FILE__, __LINE__, "Cannot open input file");
size_t uBytes = ifs.tellg (); // 經過tellg()函數獲取當前的get位置, 以此計算出文件的總字節數
char* pcBuffer = new char[uBytes]; // 有了總字節數,咱們就能夠分配足 夠的內存,一次性地讀取文件的所有內容
ifs.seekg (ios::beg); // 在讀取以前必定要將文件的 get位置重置於文件起始處
ifs.read (pcBuffer, uBytes);//讀取文件內容
ios::trunc: 打開文件的同時刪除其原有內容,用於向文件中輸入
ios::binary:以二進制模式打開文件,用於輸入/輸出
ofstream ofs ("xxx", ios::out|ios::trunc|ios::binary);
if (! ofs)
3.ifstream和ofstream用法基本相同,用於從文件中讀取
可是ifstream要求指定的文件必須存在
4.輸入流的提取操做>>在格式化提取的過程當中,以空格、製表符、換行分隔
5.fstream以讀和寫(默認)的方式打開一個文件時,文件必須存在
6.tellg/tellp:獲取當前文件位置(包括\n等)的下一個
p表示put、g表示get
tellp在將get位置調整到文件開始的同時,也改變了put位置
seekg/seekp:設置當前文件的get/set位置
1.單參: seekg(0)與seekg(ios::beg)完成相同的任務
2.雙參:
第一個參數表明相對於第二個參數所指定位置的偏移量:
ios::beg:文件頭如:fs.seekg (5, ios::beg);//從文件頭(開始下標爲0)開始數5個字符
如:1234 56.78 apples;//即5數字開始操做
ios::end:文件尾
ios::cur:當前位置如:fs.seekg (-6, ios::cur);
在上面的狀況下:tellp/tellg都獲取值爲:0
若是文件位置被移到了文件的起始位置以前或結束位置以後,那麼該文件流將進入一種錯誤狀態。
這時程序對這個流所作的更進一步處理將會被暫停,直到咱們經過clear() 函數清除了這種錯誤狀態爲止。
如:
#include <iostream>
#include <fstream>
using namespace std;
int main (int argc, char* argv[]) {
ofstream ofs1 ("ex01.txt");
if (! ofs1)
cerr << "Cannot open output file" << endl;
ofs1 << 1234 << " " << 56.78 << " " << "apples" << '\n';
ofs1.close ();
ofstream ofs2 ("ex01.txt", ios::app);
if (! ofs2)
cerr << "Cannot open output file" << endl;
ofs2 << "append_a_line\n";
ofs2.close ();
ifstream ifs1 ("ex01.txt");
if (! ifs1)
cerr << "Cannot open input file" << endl;
int n;
double f;
string str1, str2;
ifs1 >> n >> f >> str1 >> str2;
ifs1.close ();
cout << n << " " << f << " " << str1 << " " << str2 << endl;
////////////////////////////////////////////////////////////
fstream fs ("ex02.txt", ios::in | ios::out);
if (! fs)
cerr << "Cannot open file" << endl;
fs << 1234 << " " << 56.78 << " " << "apples" << '\n';
cout << fs.tellg () << endl;//獲取當前文件位置
cout << fs.tellp () << endl;//獲取當前文件位置
fs.seekg (5, ios::beg);//同seekp,都是設置當前文件位置
fs << 1;
fs.seekg (-6, ios::cur);
cout << fs.tellg () << endl;
cout << fs.tellp () << endl;
int n;
double f;
string str;
fs >> n >> f >> str;
fs.close ();
cout << n << " " << f << " " << str << endl;
return 0;
}
7.io的非格式化:
(1).ofs.put(char);//一次寫入一個字符
(char = ifs.get()) != EOF//一次獲取一個字符,不爲文件結尾
(2).get()的三參數:定界符並不被提取,但文件位置會停在定界符處,下次讀取會發生錯誤
char sz[4];
while (ifs.get (sz, sizeof (sz), '\n'))//自定義'\n'爲定界符
{
cout << sz;
cout.flush ();//刷新輸入輸出纔可能顯示出來(字符少的時候)
//注意大小爲4的sz可能沒有被填滿,由於定界符不被get讀取,因此要跳過
if (ifs.peek () == '\n')//讀當前位置的字符,但不改變文件位置
ifs.ignore ();//掠過當前位置的字符,文件位置後移
}
if (! ifs.eof ())//當前是否到了文件結尾
cerr << "Cannot read input file 1" << endl;
ifs.clear ();
(3).getline():能夠自動掠過定界符,但當其試圖讀取第二個參數-1個字符時會發生錯誤
由於當文件結束的時候,可能沒有填滿第二個參數-1個字符,這時又結束了(讀取不到字符),那麼就會出錯
char szLarge[8];
while (ifs.getline (szLarge, sizeof (szLarge), '\n'))
cout << szLarge;
if (! ifs.eof ())//當前是否到了文件結尾
cerr << "Cannot read input file" << endl;
8.字節流:
read(char*, size_t)/write(char*, size_t)
如:
char caBuffer[256];
while (ifs.read (cbBuffer, sizeof (cbBuffer)){
ofs.write (cbBuffer, sizeof (cbBuffer));
}
//可經過gcount()函數推斷出實際讀到byBuffer緩衝區中的字節數。
if (ifs.eof ())//進入某種錯誤狀態時亦返回false
ofs.write (cbBuffer, ifs.gcount ());
else
cerr << "error!" << endl;
9.流函數:
#include <math.h>
#include <iostream>
#include <iomanip>
#include <fstream>
using namespace std;
int main (int argc, char* argv[]) {
cout << sqrt (2) << endl;//1.41421
cout.precision (10);//設置小數點精度,區別不帶參數的函數(返回精度)
cout << sqrt (2) << endl;//1.414213562
cout << setprecision (10) << sqrt (2) << endl;//1.414213562
cout << sqrt (2) << endl;//1.414213562
cout << cout.precision () << endl;//10
cout << setprecision (2) << 1.24 << ", " << 1.25 << ", " << 1.26 << endl;//1.2, 1.3, 1.3
cout << oct << 127 << endl;//177
cout << hex << 127 << endl;//7f
cout << dec << 127 << endl;//127
cout << setw (7)/*注意這個函數不保存到下面的設置*/ << oct << 127 << endl;//177
cout << setw (7) << hex << 127 << endl;//7f
cout << setw (7) << dec << 127 << endl;//127
//流控制符
cout << setfill ('#') << setw (7) << oct << 127 << endl;//####177
cout << setfill ('@') << setw (7) << hex << 127 << endl;//@@@@@7f
cout << setfill ('%') << setw (7) << dec << 127 << endl;//%%%%127
cout << left << setfill ('#') << setw (7) << oct << 127 << endl;//177####
cout << left << setfill ('@') << setw (7) << hex << 127 << endl;//7f@@@@@
cout << left << setfill ('%') << setw (7) << dec << 127 << endl;//127%%%%
cout << showbase << oct << 127 << endl;//0177
cout << hex << 127 << endl;//0x7f
cout << dec << 127 << endl;//127
cout << noshowbase << oct << 127 << endl;//177
cout << dec << 127 << endl;//127
cout << 12.00 << endl;//12
cout << setprecision (10) << showpoint << 12.00 << endl;//12.00000000
cout.setf (ios::showpoint);//顯示後面的0
cout << 12.00 << endl;//12.00000000
cout.precision (4);
cout << sqrt (200) << endl;//14.14
cout.setf (ios::scientific);/*精度所限制的實際上只是底數小數部分的顯示位數*/
cout << sqrt (200) << endl;//1.4142e+001
ifstream ifs ("ex04.txt");
ifs.unsetf (ios::skipws);/*跳過空白字符(空格符、製表符以及換行 符等),
但若是出於某種緣由,咱們不但願忽略輸入流中的空白字符,
那麼咱們就可使用控制符noskipws或者調用輸入流的unsetf(ios::skipws)成員函數。
咱們也可使用操縱子skipws來取消noskipws的效果,或者調
用輸入流的setf(ios::skipws)成員函數達到一樣的目的*/
char c;
while (ifs >> c)
cout << c;
return 0;
}
10.字符串流:
(1)ostringstream對象的一個優勢是,能夠利用輸出操做符「<<」的格式化能力把數值類型的數據轉換爲它們的字符串表示形式
(2)另外:格式化字符數組
char s[1024];
sprintf (s, "money = %.2f\n", 23.44);