以二进制模式打开输入文件流时设置的 skipws 标志
Posted
技术标签:
【中文标题】以二进制模式打开输入文件流时设置的 skipws 标志【英文标题】:skipws flag set when opening an input file stream in binary mode 【发布时间】:2011-11-07 09:45:14 【问题描述】:我知道提取运算符不应该用于以二进制模式打开的输入流,但应该使用成员函数read
。
std::ifstream ifs("file.bin", std::ios::in | std::ios::binary);
char c;
ifs >> c; // Should not be used
ifs.read(&c, 1); // OK
但无论如何都可以做到。所以我的问题是,在二进制模式下打开输入文件流时不取消设置 skipws 标志的理由是什么?
【问题讨论】:
【参考方案1】:由std::ios_base::binary
控制的“二进制”模式仅用于关闭标准C++ \n
字符和存储在文件中的系统特定换行符序列之间的换行符转换。
它完全独立于您正在解析的文件是否包含有意义的分隔空白或一些完全不同的字节格式,因此没有理由将两个正交的功能结合在一起。
(C++ 标准没有详细说明二进制模式的含义,C 标准中有更多细节讨论了文本流和二进制流之间的潜在差异。二进制流必须按原样逐字节读取写在任何给定的系统上,而文本流只需要这样做,因为有许多限制,围绕在换行符之前没有额外的空格,并且除了换行符和制表符之外没有任何控制字符。系统根本不需要区分二进制和文本流。)
【讨论】:
据我所知,二进制文件是因为它的内容不会被解释为文本,因此当从二进制输入流中提取的第一个字符不是空格 (0x20) 时,我感到困惑,因为我期待着。如果像你说的那样考虑 C++ 标准的二进制模式,那很好,但仍然令人费解:) “系统根本不需要区分二进制流和文本流”-IIRC Posix 要求对于 FILE* 和文件描述符,以文本和二进制模式打开的文件之间没有区别.如果由于二进制文件设置了 skipws 位而没有设置文本位而导致 C++ 文件流的窗口消失,那将是一种耻辱。我认为基本上存在冲突 - 二进制模式说“不要弄乱我文件中的字节”,但operator>>
说,“哦,是的,做各种弄乱”。因此,我想建议不要混合它们。
@SteveJessop:我认为将二进制模式的翻译视为低级函数会更有帮助。毕竟,它发生在streambuf
级别以下,甚至不会发生在operator>>
起作用的istream
级别。 operator>>
正在进行更高级别的解析,因为它是一个格式化的输入函数。如果您想逐个字符地读取,那么您可能需要一个未格式化的读取函数(例如get
函数之一),但您仍然可能正在对文本文件进行操作。我使用了文本模式文件,但在多个应用程序中使用了低级别的streambuf::sbumpc
接口。
我同意,但是,如果您正在执行真正的逐字节二进制格式,那么将std::ios_base::binary
和未格式化的输入函数一起使用几乎总是有意义的。有时将operator>>
与二进制文件一起使用可能是有意义的,例如你已经知道要提取一个 ASCII 十进制格式的整数,或者你需要跳到一个非空白字符。
是的。无论如何,我不同意“提取运算符不应用于以二进制模式打开的输入流”。文本模式用于处理基于行的文件的操作系统约定中的怪癖。 operator>>
通常用于读取一行中以空格分隔的字段。所以这两者是独立的,但是有一个原始字节访问的用例(例如读取 mpeg 文件)。出于这个目的,你当然不想要任何一种抽象,所以如果我们想象这是有人认为二进制模式是“为”的,我想他们会说>>
破坏了二进制模式。以上是关于以二进制模式打开输入文件流时设置的 skipws 标志的主要内容,如果未能解决你的问题,请参考以下文章