逐字节读取二进制输入流

28

我试图使用 ifstream 逐字节读取二进制文件。以前,我曾经使用 get() 等 istream 方法一次性读取整个二进制文件,没有遇到问题。但我的当前任务需要逐字节读取,并依赖于 io 系统的缓冲来提高效率。问题是我似乎比应该提前几个字节到达了文件末尾。所以我写了以下的测试程序:

#include <iostream>
#include <fstream>

int main() {
    typedef unsigned char uint8;
    std::ifstream source("test.dat", std::ios_base::binary);
    while (source) {
        std::ios::pos_type before = source.tellg();
        uint8 x;
        source >> x;
        std::ios::pos_type after = source.tellg();
        std::cout << before << ' ' << static_cast<int>(x) << ' '
                  << after << std::endl;
    }
    return 0;
}

这将以每行一个字节的方式转储test.dat的内容,并显示文件位置之前和之后的内容。

如果我的文件恰好具有两个字节序列0x0D-0x0A(对应于回车符和换行符),那么这些字节将被跳过。

  • 我已经以二进制模式打开了流。这难道不能防止它解释换行符吗?
  • 提取运算符是否总是使用文本模式?
  • 什么是从二进制istream逐字节读取的正确方法?

在Windows上的MSVC++ 2008。

5个回答

25

>> 提取器是用于格式化输入的;它们默认跳过空格。如果是单个字符的非格式化输入,您可以使用istream::get()(返回一个 int,如果读取失败,则返回 EOF,否则返回范围在 [0,UCHAR_MAX] 内的值)或 istream::get(char&)(将读取的字符放入参数中,返回可转换为bool 的内容,如果读取成功,则为 true,如果失败,则为 false)。


10
哇,让我感到困惑的是我无法在没有类型转换的情况下读取二进制文件中的一个字节。 - Adrian McCarthy
1
那是因为流被设计用于文本(即使在二进制模式下打开)。通常,当读取真正的二进制数据时,我会使用系统级例程(在Unix下的open/read/write/close),而不必费心使用iostream。 - James Kanze
一个人仍然可以使用std::skipws,以便在与流操作符一起使用时,流跳过空格(和其他格式)。 - Ghita
2
@Ghita 我想你是指 std::noskipws - James Kanze
对不起,那样的话你不想跳过空格。 - Ghita

6

在C++的输入流库中,有一个名为read()的成员函数,你可以通过它指定需要读取的字节数。


5
为什么您使用格式化提取,而不是.read()呢?

8
еӣ дёәsource >> x;жҜ”source.read(reinterpret_cast<char *>(&x));жӣҙжҳ“иҜ»пјҢиҖҢдё”жҲ‘并дёҚжңҹжңӣй’ҲеҜ№дәҢиҝӣеҲ¶ж–Ү件дёӯзҡ„еҚ•дёӘеӯ—иҠӮиҝӣиЎҢжҸҗеҸ–иҝҗз®—з¬Ұдјҡжү§иЎҢд»»дҪ•ж јејҸеҢ–гҖӮ - Adrian McCarthy
.get() 对于单个字节可能比 .read() 更有效率。但是实现中可能会调用 .get 来调用 .read 或者反过来。 - Thomas Matthews
source.read((char*)&x) 更短,而且在这种情况下 C 风格的转换与 reinterpret_cast 的含义相同。 - cubuspl42
5
最好避免养成使用任何 C 风格转换的习惯,尽管如此。 - Lightness Races in Orbit

4
source.get()

这里讲的是输入函数,其中 unformatted input function 会返回一个单字节,而 formatted input function 会跳过空格字符。


2

正如其他人所提到的,您应该使用istream::read()。但是,如果您必须使用格式化提取,请考虑使用std::noskipws


不,我实际上是指noskipws。 - Robᵩ
我的意思是您仍然可以使用格式化提取(使用流运算符),只是在这种情况下必须指定skipws。 - Ghita

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接