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。

4

5 回答 5

24

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

于 2011-04-01T15:34:19.137 回答
5

有一个read()成员函数,您可以在其中指定字节数。

于 2011-04-01T12:51:55.800 回答
4

你为什么使用格式化提取,而不是.read()

于 2011-04-01T13:05:56.090 回答
4
source.get()

会给你一个字节。它是未格式化的输入函数。operator>> 是格式化的输入函数,可能意味着跳过空白字符。

于 2011-04-01T13:48:55.280 回答
2

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

于 2011-04-01T14:22:04.883 回答