1.问题
最近在帮别人调试了一个问题:
- 使用此方式获取文件大小,
struct _stat info;
_stat(filepath, &info);
int size = info.st_size;
- 使用fopen方式获取文件内容,
- 最后发现获取的字节数和第一步取得的字节数不一致,相对要小一些!
这是为什么呢?
2.分析
首先用软件打开源文件,发现是80个字节,和第一步获取的文件字节数一致,而第二步获取文件内容得到的字节数要少一些,记得是72个字节;
那么问题应该出在了第二步fopen那里,好吧,鼠标放在fopen上面按键F1,跳出微软的帮主页面,仔细愁一愁用法说明和示例~
fopen、_wfopen
VC2005中fopen的ccs=UNICODE实测<zt> + UTF8 如何转变为 ansi
简单总结下关键信息:
- fopen时候需要mode参数,即以什么配置/模式打开文件;
- 默认情况下,使用ANSI编码页解释窄文件名字符串;
- 使用UNICODE, UTF-8, 或 UTF-16LE等Unicode模式打开文件时,将会对读取到的内容进行转换成目标格式;也意味着转换后字节与原始字节很可能不一样;
- 读或写存储为UTF-8编码格式的数据时,用文本模式或者二进制模式替代Unicode模式,你得为任何编码转换负责。
Encodings Used Based on ccs Flag and BOM
Encodings Used Based on ccs Flag and BOM
ccs flag No BOM (or new file) BOM: UTF-8 BOM: UTF-16 UNICODE UTF-16LE UTF-8 UTF-16LE UTF-8 UTF-8 UTF-8 UTF-16LE UTF-16LE UTF-16LE UTF-8 UTF-16LE
mode modifier Translation mode t Open in text (translated) mode. b Open in binary (untranslated) mode; translations involving carriage-return and line feed characters are suppressed.
以unicode、t模式打开文件,会进行字节转换,转换后的字节数和原始字节数很可能不一样,如果要读取内容,要开启b(Open in binary)模式,
如果源文件是UTF-8编码的(其实不管什么编码格式文件),fopen时开启rb(read mode and open in binary)即可。
3.解决
3.1.解决此问题
fopen时开启rb(read mode and open in binary)即可读取原始内容,读到的字节数和原始字节数一致;
3.2.其他方案
也可以使用其他方式读取文件内容,参考如下,
wstring path = GetJsonFileName();
ifstream ifstream(path);
if (ifstream.fail())
return false;
stringstream buffer;
buffer << ifstream.rdbuf();
string contents(buffer.str());
ifstream.close();
当然还有其他方式,可自行搜索。
4.结论
出现上述问题是因为读取文件时因为开启了特定模式,对原始字节流进行了转换,导致转换后的字节数与原始文件字节数不一致,
如果已经确定要打开文件的编码格式(可以预先约定),那么只要开发rb模式即可读取原始内容。
另外遇到问题一般光标放在要了解的接口上F1键即可弹出帮主页面,内容详细清晰,有很大帮助。