【问题标题】:Why would I ever open a file (std::ifstream) without std::ios::binary?为什么我会在没有 std::ios::binary 的情况下打开文件 (std::ifstream)?
【发布时间】:2013-12-20 13:40:26
【问题描述】:

这可能属于 Stack Exchange 的不同部分,但我不这么认为——programmers.se 更多的是关于其他事情。

提出问题:有些事情你可以用 std::ios::binary 做而你不能在文本模式下做(例如相对搜索),但我找不到在文本模式下你不能用二进制做的任何事情模式 - 甚至将文件作为文本读取,例如std::getline()

那么为什么我会以文本形式打开呢?作为一个可能相关的问题,为什么不默认打开二进制文件?这会破坏谁的用例?

编辑附加信息

这就是我要问的原因:

我有一个在 Windows 系统上创建的文件 - 也就是说,行结尾是 CR LF。

我用std::ifstream 使用std::ios::binary 标志打开它

我正在使用 std::getline 解析文件并获得我所期望的行为 - getline 一次读取一行。

系统:Windows 7 专业版

编译器:用于 MINGW32 的 g++

【问题讨论】:

  • 不确定标准库是否这样做,但在文本文件的开头可能会有一些文本编码字节和字节顺序掩码。如果以文本模式打开,标准库可能会正确解释它们并跳过它们?但是在二进制模式下将它们视为非特殊字节?
  • 曾经有这样的想法,即您将与平台无关地读写“文本文件”。因此,您想使用适合该平台的任何行分隔符。对于那些在 Windows 上使用除记事本以外的任何文本编辑器的人来说,我认为这个想法已经大行其道——在任何平台上,您都可以只编写 LF 并在阅读时接受这两种换行符。但即使你接受(不是每个人都会接受),更改默认值也是不必要的不​​兼容。
  • @medivh:在 Windows 上,以文本模式打开文件意味着如果文件包含\r\n,它将被读取为\n。因此,使用默认值并期望看到\n 的代码将被破坏。它将改为看到\r\n。因此,例如,您可能会在从文件读取的值上得到一个尾随 \r,因为删除 \n 不再删除整个换行序列。 没有来自其他来源的错误\r 将无法匹配等效值。
  • @medivh:所以要明确一点:因为您有一些代码在看到 \r 时可以工作,您几乎可以完全确定不存在在看到 @987654332 时无法工作的有效代码@?我不认为以下 ;-) 或者您的意思是您不相信以二进制模式打开包含\r 的文件会导致代码看到\r 字符?这可以通过几行测试代码轻松确认。
  • @medivh 他肯定没有错。在过去的几年里,我不得不解析在 Windows 上编写的文件,在 Unix 机器上解析,而额外的 '\r' 确实给我带来了额外的工作。

标签: c++ fstream


【解决方案1】:

在文本模式下你能做什么而在二进制模式下你不能做到?读 文本,对于初学者。以文本模式自动打开的文件 在内部的'\n' 字符和其他字符之间转换 系统用于在外部分隔文件中的行。它可以 也可以识别文件的任意结尾,即使 底层系统要求文件大小是某些的倍数 固定大小。

今天的选择有点复杂,因为您 通常必须从不兼容的系统访问文件。如果 你有一个文件系统安装在 Windows 和 Unix 上,写 在 Windows 下作为文本,在 Unix 下作为文本读取,然后 你会看到额外的字符。在这种情况下,它可能是 最好读写二进制,并做行尾 根据您喜欢的任何约定来处理自己。 同样,如果“文件”实际上是一个套接字,则通信 用另一台机器,你会想用二进制打开它,然后 自己处理行尾,根据要求 协议。

【讨论】:

  • “从不兼容的系统访问文件”——他们还以二进制方式共享该文件。如果文件由内容感知机制(例如 SVN)共享,则该机制可能会为您进行相关转换。
  • @MSalters 当我说“分享”时,我的意思是“分享”。一个共享文件系统,安装在几个不同的系统上。这似乎是我工作过的大多数地方的常见情况(当他们有任何 Windows 机器时)。
  • @medivh:您在编辑中描述的行为是有道理的,但是当文件以二进制模式打开时,我希望您阅读的每一行的末尾都有\r。也许这不会损害您的程序,但可能会损害其他人的程序。我手头没有 mingw 可以检查,所以我不能告诉你它在文本模式下的作用——一方面它在 Windows 中运行,所以它可能会尊重 Windows 换行符。另一方面,它应该提供一个模糊的类似 Posix 的环境,而 Posix 要求二进制模式和文本模式是相同的。
  • @medivh:我能找到的所有在线提及都说 mingw 默认确实以文本模式打开。所以getline的结果应该是有区别的。您的特定程序是否真的因为二进制模式下额外的\r 而出错是另一回事。
  • @medivh 为 Windows 或 Unix 重新编译:大多数库在阅读时都试图有点不可知论。 Windows下写'\n'时,系统会将两个字节写入文件;当您在 Windows 下阅读时,我知道的库会将隔离的 '\n' 视为前面有 '\r'。在Unix下,多余的'\r'会出现在你读到的那一行;这是否会导致问题取决于您如何解析该行。
【解决方案2】:

标准输入默认在文本模式下打开,这允许使用例如 CTRL + Z 来发出 EOF 信号,所以我不明白为什么你认为除了二进制模式之外没有“需要”在任何情况下打开流.

【讨论】:

    猜你喜欢
    • 2013-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-16
    • 2020-10-19
    • 2011-01-19
    • 1970-01-01
    相关资源
    最近更新 更多