【问题标题】:Difference between opening a file in binary vs text [duplicate]以二进制文件与文本文件打开文件的区别[重复]
【发布时间】:2014-01-18 18:43:19
【问题描述】:

我做过一些类似的事情:

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 有什么区别。

我在哪里读到了 fopen 模式:http://www.cplusplus.com/reference/cstdio/fopen/

【问题讨论】:

  • 尝试在 Windows 上以文本模式打开文件并在其中写入一堆换行符,然后尝试将其读回。
  • 是的,我现在看到了副本。很抱歉之前没有注意到它
  • 旁注:我注意到你用 C++ 标记了这个,而不是 C。我可以建议使用 std::ifstreamstd::ofstream 而不是 C 库吗?它更加地道,并确保您不必担心记住调用 close,无论是否抛出异常(除了提供其他不错的抽象之外)。
  • @Mark 我会调查的。
  • 请注意,在我写这篇文章时,链接到副本的所选解决方案在某些细节上是不正确

标签: c++ file text binary


【解决方案1】:

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

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

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

转换可能是将\r\n 标准化为\n(反之亦然),或者可能忽略 0x7F 以外的字符(FTP 中的“文本模式”)。就我个人而言,我会以二进制模式打开所有内容,并使用良好的 Unicode 或其他文本编码库来处理文本。

【讨论】:

  • 我本来不打算处理文本,所以这很好。出于某种原因,直到 10 分钟后我才能接受。
【解决方案2】:

需要注意的最重要的区别是,在文本模式下打开流时,您会在非 *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 应为 对与同一文件和whence 关联的流上的ftell 函数的较早成功调用应为SEEK_SET

关于 ftell 的使用,见 §17.19.9.4:

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

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

【讨论】:

    猜你喜欢
    • 2011-08-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-27
    • 2015-04-02
    • 2014-04-08
    • 1970-01-01
    相关资源
    最近更新 更多