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

BWG*_*BWG 9 c++ binary text file

我做过一些像:

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

然后在生成的文本文件中,它就像预期的那样说"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);
Run Code Online (Sandbox Code Playgroud)

并获得完全相同的结果.如果我使用二进制或普通模式读取文件,它也会给我相同的结果.所以我的问题是,有或没有二进制模式的fopening有什么区别.

我在哪里读到有关fopen模式的信息:http://www.cplusplus.com/reference/cstdio/fopen/

Dai*_*Dai 12

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

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

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

转换可能是归\r\n\n(反之亦然),或可能忽略超出0x7F的(一拉在FTP"文本模式")字符.就个人而言,我会以二进制模式打开所有内容,并使用一个好的文本编码库来处理文本.


Che*_*Alf 6

要注意的最重要的区别是,在文本模式下打开流,您可以在非*nix系统上获得换行符(它也用于网络通信,但标准库不支持此功能).在*nix中,换行符只是ASCII换行符,\n用于文本的内部和外部表示.在Windows中,外部表示通常使用回车符+换行符对"CRLF"(ASCII代码13和10),它\n在输入时转换为单个,反之亦然.


根据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呼叫时的位置; 两个这样的返回值之间的差异不一定是写入或读取的字符数的有意义的度量.

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