天天看点

c++读取文件字节数和源文件大小不一致情况分析及解决1.问题2.分析fopen、_wfopen3.解决4.结论

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键即可弹出帮主页面,内容详细清晰,有很大帮助。

继续阅读