【问题标题】:Best way to read binary file c++ though input redirection通过输入重定向读取二进制文件 c++ 的最佳方法
【发布时间】:2017-02-07 00:21:53
【问题描述】:

我正在尝试在运行时读取一个大型二进制文件,考虑输入重定向 (stdin),而stdin 是强制性的。

./a.out < input.bin

到目前为止,我已经使用了 fgets。但是 fgets 会跳过空格和换行符。我想包括两者。我的currentBuffersize 可以动态变化。

FILE * inputFileStream = stdin; 
int currentPos = INIT_BUFFER_SIZE;
int currentBufferSize = 24; // opt
unsigned short int count = 0; // As Max number of packets 30,000/65,536
while (!feof(inputFileStream)) {
    char buf[INIT_BUFFER_SIZE]; // size of byte
    fgets(buf, sizeof(buf), inputFileStream);
    cout<<buf;
    cout<<endl;
}

提前致谢。

【问题讨论】:

  • fread 用于未处理的输入。 fgets 正如你所说的那样进行文本处理。 不要忽略返回值,即存储到缓冲区的有效记录数。
  • 查看“stackoverflow.com/questions/7587595/…”重复?答案是你不能。
  • 为什么在 C++ 中使用 C stdio?
  • @DOUGLASO.MOEN 是的,你可以。首先,这个问题是专门关于用cin 做的,所以它与这个问题并没有真正的关系,其次,那里的答案实际上告诉你如何去做。 这个问题只是未能阅读 stdio 的文档/未能在 Google 上搜索 "read binary data from stdin"
  • @JasonC ...谢谢,第一次阅读时我没有区分 stdin 和 std::cin。

标签: c++ stream stdin cin


【解决方案1】:

如果是我,我可能会做类似的事情:

const std::size_t INIT_BUFFER_SIZE = 1024;

int main()
{
    try
    {
        // on some systems you may need to reopen stdin in binary mode
        // this is supposed to be reasonably portable
        std::freopen(nullptr, "rb", stdin);

        if(std::ferror(stdin))
            throw std::runtime_error(std::strerror(errno));

        std::size_t len;
        std::array<char, INIT_BUFFER_SIZE> buf;

        // somewhere to store the data
        std::vector<char> input;

        // use std::fread and remember to only use as many bytes as are returned
        // according to len
        while((len = std::fread(buf.data(), sizeof(buf[0]), buf.size(), stdin)) > 0)
        {
            // whoopsie
            if(std::ferror(stdin) && !std::feof(stdin))
                throw std::runtime_error(std::strerror(errno));

            // use {buf.data(), buf.data() + len} here
            input.insert(input.end(), buf.data(), buf.data() + len); // append to vector
        }

        // use input vector here
    }
    catch(std::exception const& e)
    {
        std::cerr << e.what() << '\n';
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}

请注意,您可能需要在二进制模式中重新打开 stdin,但不确定它的可移植性如何,但各种文档表明跨系统得到了相当好的支持。

【讨论】:

  • 我最近开始用 C++ 编程,你能解释一下这个方法 fread(buf.data(), sizeof(buf[0]), buf.size(), stdin)) ... 我了解此函数读取未处理的文件流 - 标准输入,但我迷失在前三个参数...
  • @Jerry 它可能值得阅读文档:en.cppreference.com/w/cpp/io/c/fread 如果您只关心读取字节,那么只需将第二个参数设置为1,然后第三个参数说明要读取多少字节。有时人们一次读取字节块,因此他们将第二个参数设置为每条记录(块)中的字节数。在所有情况下,要读取的字节数都是第二个和第三个参数中大小的乘积。
  • 我使用了sizeof(buf[0]),因为如果我将std::array 更改为包含大于char 的对象,std::fread 的参数将自动调整。
  • 哦..我明白了.. fread 应该读取空白和换行符也不是...但是由于某种原因它跳过了它们..
  • @Jerry 如果您按照我的示例在二进制模式下freopn,则不应跳过它们,尤其是。如果它继续跳过它们,我建议您编辑您的问题,发布一个完整的代码示例,该示例会产生您所描述的错误。
猜你喜欢
  • 1970-01-01
  • 2016-06-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-20
  • 2021-07-06
  • 1970-01-01
相关资源
最近更新 更多