一、檔案的讀寫
如前面所提,流的讀寫主要有<<, >>, get, put, read, write 等操作,ofstream 繼承自ostream, ifstream 繼承自 istream,故操作函數都是一致的。
C++ Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
|
|
#include <iostream> #include <fstream> #include <string> #include <cassert> using namespace std;int main(void) { ofstream fout("test.txt"); fout << "abc" << " " << 200; fout.close(); ifstream fin("test.txt"); string s; int n; //fin>>n>>s; fin >> s >> n; cout << s << " " << n << endl; ofstream fout1("test2.txt"); assert(fout1); char ch; for (int i = 0; i < 26; i++) { ch = 'A' + i; fout1.put(ch); } fout1.close(); ifstream fin1("test2.txt"); while (fin1.get(ch)) { cout << ch; } cout << endl; return 0; } |
二、二進位檔案的讀寫
二進位檔案不同於文字檔,它可用於任何類型的檔案(包括文字檔)
對二進位檔案的讀寫可採用從istream類繼承下來的成員函數read()和從ostream類繼承下來的成員函數write()
檔案開啟操作時使用枚舉常量ios::binary,例如:ofstream fout(“binary.dat”,ios::out | ios::binary);
(一)、write成員 函數
函數功能:以位元組位單位向檔案流中寫入整塊資料,最有價值的應用可以處理結構體變數和類對象
函數原型:
ostream& write( const char* pch, int nCount );
函數參數:
pch 寫入的資料的指標
nCount 寫入資料的位元組大小
(二)、read 成員 函數
函數功能:從檔案流中讀出整塊資料
函數原型:
istream& read( char* pch, int nCount );
函數參數:
pch 用來接收資料的指標
nCount 讀取的位元組數的大小
C++ Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
|
|
#include <cassert> #include <iostream> #include <fstream> #include <string>using namespace std; struct Test { int a; int b; }; int main(void) { ofstream fout("test3.txt", ios::out | ios::binary); // 二進位方式開啟,'\n'不做轉換 fout << "ABC\n"; // << 是以文本方式寫入 fout.close(); Test test = { 100, 200 }; ofstream fout1("test4.txt", ios::out | ios::binary); fout1.write(reinterpret_cast<char *>(&test), sizeof(Test)); // 二進位方式寫入後用文字編輯器開啟test4.txt 亂碼 fout1.close(); Test test2; ifstream fin("test4.txt", ios::in | ios::binary); fin.read(reinterpret_cast<char *>(&test2), sizeof(Test)); cout << test2.a << " " << test2.b << endl; ofstream fout2("test5.txt", ios::out | ios::binary); fout2 << "abc" << 200; // << 是以文本方式寫入 fcout2.close(); return 0; } |
在window下以文本方式開啟檔案,則寫入時遇到'\n' , 轉換為'\r\n',以二進位方式開啟則不做轉換,故test3.txt 檔案大小為4個位元組。
而寫入100(write 是以二進位方式寫入)就不再是寫入'1', '0' ,' 0' 的ascii 碼,而是按照記憶體本來二進位形式寫入,故用文字編輯器開啟test4.txt 時會出現亂碼。檔案大小為8個位元組(兩個int)
同理,test5.txt 雖然以二進位開啟,但是以文本方式(<< 是以文本方式寫入)寫入的,故寫入200後用文字編輯器開啟不會出現亂碼,檔案大小為6個位元組。
有關文字檔與二進位檔案的區別,請參考這裡。
使用read, write 讀取string 的時候需要注意,string 實際上內部是一些指標成員,sizeof(string)=32 (跟編譯器實現有關),即string 大小是一定的,而它的指標成員儲存的字串長度不一定是32,故我們應該這些讀寫:
C++ Code
1 2 3 4 5 6 7 8 9
|
|
string str1 = "fdsfafsdsf"; int len = str1.length(); ofstream fout("test6.txt", ios::out | ios::binary); fout.write(str1.data(), str1.length());string str2; str2.resize(len); ifstream fin("test6.txt", ios::in | ios::binary); fin.read(&str2[0], len); |
如果像這樣寫入 fout.write((char*)&str1, sizeof(str1)); 一定是錯誤的,因為寫入的是str1 的指標成員,而不是指標成員指向的字串,而且str1 的大小恒等於32。
三、檔案隨機讀寫
(一)、當前檔案流活動指標
檔案流指標用以跟蹤發生 I/O 操作的位置
每當從流中讀取或寫入一個字元,當前活動指標就會向前移動
當開啟檔案中不含有ios::ate或ios::app選項時,則檔案指標被自動移到檔案的開始位置,即位元組地址為0的位置。
(二)、檔案的隨機讀寫 seekp和seekg
seekp 和 seekg 類似與C庫的fseek, linux系統調用的lseek。
函數功能
seekp:設定輸出檔案流的檔案流指標位置
seekg:設定輸入檔案流的檔案流指標位置
函數原型:
ostream& seekp( streampos pos );
ostream& seekp( streamoff off, ios::seek_dir dir );
istream& seekg( streampos pos );
istream& seekg( streamoff off, ios::seek_dir dir );
函數參數
pos:新的檔案流指標位置值
off:需要位移的值
dir:搜尋的起始位置
dir參數用於對檔案流指標的定位操作上,代表搜尋的起始位置
在ios中定義的枚舉類型:
enum seek_dir {beg, cur, end};
每個枚舉常量的含義:
ios::beg:檔案流的起始位置
ios::cur:檔案流的當前位置
ios::end:檔案流的結束位置
tellp 和 tellg 類似C庫的ftell,,linux 系統調用的lseek(fd, 0, SEEK_CUR);
函數功能
tellp:獲得輸出的檔案流指標的當前位置,以位元組為單位
tellg:獲得輸入的檔案流指標的當前位置,以位元組為單位
函數原型:
streampos tellp();
streampos tellg();
函數傳回值:實際上是一個long類型
C++ Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
|
|
#include <cassert> #include <iostream> #include <fstream> #include <string>using namespace std; int main(void) { ifstream fin("test7.txt"); assert(fin); fin.seekg(2);//位置從0開始計數
char ch; fin.get(ch); cout << ch << endl; fin.seekg(-1, ios::end); //end 實際上是EOF位置 fin.get(ch); cout << ch << endl; fin.seekg(0, ios::end); streampos pos = fin.tellg(); cout << pos << endl; return 0; } |
假設test7.txt 現在存放abcdefg 7個字元,則輸出為c g 7 .
參考:
C++ primer 第四版
Effective C++ 3rd
C++編程規範