问题描述:
当用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代替。
尚没有找到简单完美的方式解决流读取文件大小的问题,如果你有好的方法,请回复。