問題描述:
當用ios::in模式打開文件時,使用seekg和tellg讀取文件的長度,將讀取文件內容輸出到控制台,發現亂碼。
1 int _tmain(int argc, _TCHAR* argv[]) 2 { 3 using namespace std; 4 ifstream stream("F:\\WorkSpace\\StreamDemo\\Debug\\abc.txt", ios::in); 5 if(!stream) 6 cerr << "Open failed" << endl; 7 stream.seekg(0, ios::end); 8 int len = stream.tellg(); 9 stream.seekg(0, ios::beg); 10 char* buffer = new char[len]; 11 memset(buffer, '\0', len); 12 if(!stream.read(buffer, len)) 13 { 14 cout << "Read error:" << stream.rdstate() << endl; 15 } 16 cout.write(buffer, len); 17 stream.close(); 18 system("pause"); 19 return 0; 20 }
abc.txt文件內容:
運行結果如下:
讀出結果錯誤,輸出到控制台文件,最后有兩個亂碼。
而將ios::in改為ios::binary之后,運行結果如下
單步調試發現,得到的len為8,而文件中的內容本以為是a\naaa\n,應該是6個。
經調查,發現在windows的文本文件中換行是兩個字符\r\n,所以文件中的內容為a\r\naaa\r\n這8個字符。
而用ios::in方式讀入的文件為a\naaa\n,所以len超過文件末尾。
而用ios::binary方式讀入的文件為a\r\naaa\r\n,得到正確的結果。
又改使用了get()來獲得結果,依然發現得到的結果是a\naaa\n。
得出以下結論:
1. 以ios::in方式讀入的文件,/r/n讀取內存之后會被認為是同一個字符/n,/n寫入文件變成/r/n
2. 以ios::binary方式讀取的文件,/r/n讀取內存之后會被認為是兩個字符,寫入文件時,必須把換行符寫入為/r/n,否則起不到換行效果。
3. 上述seekg和tellg的方式,用作計算ios::in方式打開的文件長度,實際值大於文件讀入之后的長度。不能用read讀取文件,可用get或getline代替。
尚沒有找到簡單完美的方式解決流讀取文件大小的問題,如果你有好的方法,請回復。