fread函数读取到的数据和实际数据不同

背景

最近项目中弄个接口,涉及到二进制文件处理,刚开始对读写文件夹这块没有太注意,结果最后浪费了一些时间。函数

文件大小600+k(不到一兆),二进制存储,总长度638208个字节,以下:spa

正文

最初,经过fopen打开文件,以下:.net

/* 打开文件*/
if((fp_input = fopen(strFilePath.GetBuffer(), "r")) == NULL)
{
    MessageBox("Can't open intput file!");
}

而后获取文件的总长度,以下:code

/* 获取文件总长度(总字节数) */
long filesize(FILE *stream)
{
	long curpos, length;

	curpos = ftell(stream);
	fseek(stream, 0L, SEEK_END);
	length = ftell(stream);
	fseek(stream, curpos, SEEK_SET);
	return length;
}

一切看似都很正常,文件能打开,总长度获取也没问题,而后就是经过fread读取文件内容了,以下:blog

/* 读取文件内容 */
if(fread(str_file, 1, flength, fp_input) == 0)
{
    MessageBox("Can't read file!");
	return;
}

OK,下面就开始根据接口格式解析文件内容了。接口

问题也就出来了,明明文件总长度为638208个字节,但每次处理到629000+个字节后程序就崩掉了。开始我觉得是我解析代码里面内存没处理好形成内存溢出了,而后我就把全部分配内存的地方注释掉,发现还有问题。调了一段时间后,我就在函数入口的地方直接偏到629000+的位置看了内存里面的内容,发现居然为空。如今就定位了问题出在前面的读文件,往前看代码,发现fopen的时候用的“r”,改为“rb”,从新跑了下程序。OK了,OK了,OK了,为何?内存

为何用“r”和“rb”都能读取文件内容,但读出来的东西却不同了?get

带着疑问,在网上搜了一把(以前确实没注意过这个问题,也没遇到过),发现真有这样的问题,缘由以下:input

先看一段MSDN:

If the given stream is opened in text mode, carriage return–linefeed pairs are replaced with single linefeed characters. The replacement has no effect on the file pointer or the return value.

就是说若是按“文本模式”打开一个文件,那么在读入的时候,Windows默认的换行符CR+LF就会转换成一个单个的LF。it

引自:https://blog.csdn.net/tgdzsjh/article/details/32702073

r遇到0x0d后面没有0x0a会自动加一个,遇到0x1a会忽略后面的内容
rb不会

r 读到\r\n会改成\n,读到\x1a会返回EOF
rb 读到什么返回什么,读到文件末尾才会返回EOF

引自:https://blog.csdn.net/cattylll/article/details/7107089

相关文章
相关标签/搜索