【问题标题】:Having trouble understanding binary file reading无法理解二进制文件读取
【发布时间】:2025-12-20 04:40:11
【问题描述】:

下面是我发现的一些代码,据我所知,这些代码读入二进制文件。我已经评论了我认为正在发生的事情,但是我无法识别 memblock 到底是什么/它正在存储什么。是整个二进制文件吗?

void BinaryFiles(string sfile){
    streampos size;                               //creates object to store size of file
    unsigned char* memblock;
    ifstream file(sfile, ios::in | ios::binary);  //creates file object(which opens file)
    if (file.is_open())
    {
        file.seekg(0, ios::end);                 //find end of file
        size = file.tellg();                     //sets size equal to distance from beginning
        memblock = new unsigned char[size];      //dynamically allocates memblock to char array
        file.seekg(0, ios::beg);                 //find beginning of file
        file.read((char*)memblock, size);        //this is where confusion begins
        cout << memblock << endl;                //what am I printing?
        file.close();
        delete[] memblock;
}
}

【问题讨论】:

  • cout &lt;&lt; memblock &lt;&lt; endl; //what am I printing? 好问题:从文件中读取的内容。但是,它可能不适合cout。想象一下,二进制文件中的第一个字节是0。然后,cout &lt;&lt; memblock &lt;&lt; endl; 将只打印新行。对于任意二进制的输出,例如某种hexdump 是更好的选择。
  • 看看文档。的std::istream::read()。第一个参数。是指向目标缓冲区(适当大小)的指针,第二个参数。是要读取的字符数。所以,是的,它会读取整个文件。

标签: c++ binaryfiles


【解决方案1】:
//这是混乱开始的地方

好的,那么让我们从这里开始:

file.read((char*)memblock, size); 

这告诉ifstream 将特定数量的字节 (size) 读取到您作为指针 (memblock) 提供的某个内存缓冲区中。

然而,read 接受一个指向char 的指针,但缓冲区被创建为unsigned char,所以我们进行了转换。

cout << memblock << endl;

将输出您刚刚阅读的文件的内容。实际上,它只会在遇到第一个空字符之前打印,因此它可能会截断文件内容。但是,如果文件根本不包含空字符,您会得到未定义的行为,因为 operator&lt;&lt; 然后将读取超出缓冲区的范围。

【讨论】:

    【解决方案2】:

    memblock 分配给 new unsigned char[size]; 其中 size 是由 @987654327 给出的文件大小@

    file.seekg(0, ios::end);
    size = file.tellg();
    

    前两行用于获取文件的大小

    file.read((char*)memblock, size);
    

    然后继续将文件内容读入 memblock。因此,为了回答您的问题, memblock 正在存储文件的全部内容。

    来自std::basic_istream&lt;CharT,Traits&gt;::read

    从流中提取字符。

    表现为 UnformattedInputFunction。构建和检查后 哨兵对象,提取字符并将它们存储到连续的 第一个元素指向的字符数组的位置 s。提取并存储字符,直到出现以下任何情况 条件发生:

    • count 个字符被提取并存储

    • 文件结束条件出现在输入序列上(在这种情况下,调用 setstate(failbit|eofbit))。成功数 可以使用 gcount() 查询提取的字符。

    最后当你这样做时:

    cout << memblock << endl;
    

    这将打印已读入memblock

    的文件内容

    【讨论】:

    • 我明白了,但是由于 memblock 是一个字符数组,我不应该编写一个 for 循环来打印它的所有元素吗?@smac89
    • @Risen,你不需要循环。您当然可以这样做,但是正如您所看到的 herestd::basic_ostream &lt;&lt; 运算符被重载以处理打印 char*
    • @Scheff 准确地说:接受unsigned char 的重载实际上是free-standing(承认,但不会改变基本语句......)。
    • @smac89 实际上,memblock 的类型是 const unsigned char*。尽管如此,结果并没有改变——operator&lt;&lt; 也有(std::ostream&amp;, const unsigned char*) 的重载(它也是如此)。 ;-)