Windows下读文件二进制模式和文本模式的区别

发布时间 2023-11-30 10:20:41作者: 快雪

前段时间,碰到了一个奇怪的事情,我实现了一个读某文件的类,原本这个文件是以二进制写的,读的时候没太在意,将模式少写了一个“b”,变成了文本模式

_tfopen_s(&pFile, m_file, _T("r"))

测试了好些文件都没有问题,直到有一天,一同事反应读取函数有问题,数据被截断了。我看了半天,百思不得其解。抱着试试的态度,把模式改成了“rb"后,一切又恢复了正常。问题是解决了,但是,对于文本模式与二进制模式的区别,却始终没有搞清楚。

直到昨天,一同事发给我一段文字:

二进制与文本模式

文本流是能组合成行(零或更多字符加上终止的 '\n' )的有序字符序列;行能分解成零或多个字符加一个终止的 '\n' (“换行”)字符。最后一行是否要求终止的 '\n' 是实现定义的。另外,可能必须在输入与输出时添加、切换或删除字符,以符合 OS 中的表示文本(尤其是 Windows OS 上的 C 流在输出时将 '\n' 转换为 '\r\n' ,输入时将 '\r\n' 转换为 '\n' )。

仅若下列条件全为真,从文本流读取的数据才保证与先前写出到该文本流者比较相等:

  • 数据由打印字符和/或控制字符 '\t' 及 '\n' 组成(尤其是 Windows OS 上,字符 '\0x1A' 终止输入)。
  • 无立即为空格符所前驱的 '\n' 字符(当这种输出随后作为输入读入时,这种空格字符可能消失)。
  • 末字符是 '\n' 。

二进制流是能通透地记录内部数据的有序字符序列。从二进制流读取的数据始终与先前写出到该流者比较相等,除了允许实现后附不确定数量的空字符到流结尾。宽二进制流不必终止于初始迁移状态。

原来,在Windows系统下以文本模式读文件时,遇到0x1A即认为文件结束(EOF),因此,文件被截断了。我验证了一下我读的文件,确实如此,如下图:

图1 文件二进制

图2 调试器结果

从图2可以看出只读了check_sum这一个字段,我将9547011转换为16进制是:0x91AD03

 和图1进行对比,考虑到字节序问题,也就说在0x1A处被截断了。

关于Windows系统为什么会将0x1A认为是EOF(现在这个值是-1),这是一个历史问题,最多的说法是,在早期0x1A就是EOF,这个故事很长,想了解详情的可以自己查阅。

参考:

【1】https://zh.cppreference.com/mwiki/index.php?title=cpp/io/c/FILE&variant=zh

【2】https://blog.csdn.net/zhoubl668/article/details/7054282