打开二进制文件与文本之间的区别

时间:2013-12-31 22:51:02

标签: c++ file text binary

我做过一些像:

FILE* a = fopen("a.txt", "w");
const char* data = "abc123";
fwrite(data, 6, 1, a);
fclose(a);

然后在生成的文本文件中,它就像预期的那样说“abc123”。但后来我做了:

//this time it is "wb" not just "w"
FILE* a = fopen("a.txt", "wb");
const char* data = "abc123";
fwrite(data, 6, 1, a);
fclose(a);

得到完全相同的结果。如果我使用二进制或普通模式读取文件,它也会给我相同的结果。所以我的问题是,使用或不使用二进制模式之间有什么区别。

我读到有关fopen模式的内容:http://www.cplusplus.com/reference/cstdio/fopen/

2 个答案:

答案 0 :(得分:12)

您提供的链接确实描述了这些差异,但它隐藏在页面底部:

http://www.cplusplus.com/reference/cstdio/fopen/

  

文本文件是包含文本行序列的文件。 根据应用程序运行的环境,在文本模式下的输入/输出操作中可能会发生一些特殊字符转换,以使其适应系统特定的文本文件格式。虽然在某些环境中不会发生转换,并且文本文件和二进制文件的处理方式相同,但使用适当的模式可以提高可移植性。

转换可能是将\r\n规范化为\n(反之亦然),或者可能忽略超过0x7F的字符(在FTP中为a-la'text mode')。就个人而言,我会以二进制模式打开所有内容,并使用一个好的Unicode或其他文本编码库来处理文本。

答案 1 :(得分:6)

要注意的最重要的区别是,在文本模式下打开流,您会在非* nix系统上获得换行符(它也用于网络通信,但这不是由标准库支持)。在* nix中,换行符只是ASCII换行符\n,用于文本的内部和外部表示。在Windows中,外部表示通常使用回车符+换行符对,“CRLF”(ASCII代码13和10),在输入时转换为单个\n,相反在输出时转换为。{/ p>


根据C99标准(N869草案文件),§7.19.2/ 2,

  

文本流是按行排列的有序字符序列,每行   由零个或多个字符加上终止的换行符组成。是否   最后一行要求终止换行符是实现定义的。人物   可能必须在输入和输出上添加,更改或删除以符合不同   用于在主机环境中表示文本的约定。因此,不需要一个 -   流中的字符与外部字符之间的对应关系   表示。从文本流读入的数据必须与数据相等   只有在以下情况下才会写入该流:数据仅包含打印   字符和控制字符水平制表符和换行符;没有换行符   紧接着前面有空格字符;最后一个字符是换行符。   是否在新行字符之前立即写出的空格字符   读入时出现的是实现定义。

§7.19.3/ 2

  

二进制文件不会被截断,除非在7.19.5.3中定义。是否写在文本上   流导致关联文件被截断超过该点是实现 -   定义

关于fseek的使用,见§7.19.9.2/ 4:

  

对于文本流,offset应为零,或offset应为返回的值   早先成功调用与同一文件关联的流上的ftell函数,whence应为SEEK_SET

关于ftell的使用,见§17.19.9.4:

  

ftell函数获取stream指向的流的文件位置指示符的当前值。对于二进制流,该值是文件开头的字符数。对于文本流,其文件位置指示符包含未指定的信息,fseek函数可使用该信息将流的文件位置指示符返回到ftell调用时的位置;两个这样的返回值之间的差异不一定是写入或读取的字符数的有意义的度量。

我认为这是最重要的,但还有一些细节。