【问题标题】:Reading data from binary file从二进制文件中读取数据
【发布时间】:2011-02-02 11:55:32
【问题描述】:

我正在尝试从二进制文件中读取数据,但遇到了问题。我已将其简化为这里最简单的情况,但它仍然无法正常工作。我是 C++ 新手,所以我可能会做一些愚蠢的事情,但是如果有人可以建议我将非常感激。

代码:

int main(int argc,char *argv[]) {
    ifstream myfile;
    vector<bool> encoded2;

    cout << encoded2 << "\n"<< "\n" ;

    myfile.open(argv[2], ios::in | ios::binary |ios::ate );
    myfile.seekg(0,ios::beg);
    myfile.read((char*)&encoded2, 1 );
    myfile.close();


    cout << encoded2  << "\n"<< "\n" ;

}

输出

00000000

000000000000000000000000000011110000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 P>

Compression_Program(58221) malloc: * 对象 0x10012d 错误:未对齐指针被释放 * 在 malloc_error_break 中设置断点进行调试

提前致谢。

【问题讨论】:

  • 什么是编码 2 的向量 a std::vector ?使用 &encoded2[0] 并调整向量的大小。

标签: c++ memory binary-data


【解决方案1】:

不要将vector&lt;bool&gt;* 转换为char*。它不会做任何可预测的事情。

【讨论】:

    【解决方案2】:

    您正在阅读编码2:myfile.read((char*)&amp;encoded2, 1 );。这是错误的。您可以读取一个布尔值,然后将其放入编码2

    bool x;
    myfile.read( &x, 1 );
    encoded2[0] = x;
    

    【讨论】:

      【解决方案3】:

      这里有两个错误:

      • 假设向量的地址是第一个元素的地址
      • 你依赖vector&lt;bool&gt;

      将向量转换为char * 并不是一件好事,因为向量是一个对象,它存储了一些状态及其元素。

      这里你可能覆盖了向量的状态,因此析构函数失败了。

      也许您想转换向量的元素(保证在内存中连续存储)。但另一个陷阱是vector&lt;bool&gt; 可能是实现优化的。

      因此,您应该使用encoded2.reserve(8) 并使用myfile.read(reinterpret_cast&lt;char *&gt;(&amp;encoded2[0]))

      但可能你想做其他事情,我们需要知道这里的目的是什么。

      【讨论】:

      • 我基本上是在编写一个解压缩程序,从文件的已知部分获取一个二进制数据块,然后使用编码将其转换回正确的形式。因此,我需要收集大量的二进制数据。这会改变事情吗?
      • 是的,但是为什么要使用bools 的向量来存储二进制数据呢? char 的向量不是更好吗?这样你就不会有字节序问题。
      • @Benoit 1) 如果矢量存储在位图中,将不起作用 2) 对于这种情况,您必须使用 2 static_cast-s 而不是 reinterpret_cast。 reinterpret_cast 是实现定义的操作。
      • 我使用的是布尔向量,因为它是其他人编写的函数的输出。不确定这是否好用,我真的是 C++ 新手,并且仍在掌握最佳实践。
      • 我只是想做一些类似这里所做的事情:courses.cs.vt.edu/~cs2604/fall02/binio.html 在标题“读取和写入复杂数据”下
      【解决方案4】:

      您正在覆盖 std::vector,这是您不应该这样做的。 std::vector 实际上是一个指向数据数组的指针和一个保存其大小的整数(可能是size_t);如果你用几乎随机的位覆盖这些,就会发生数据损坏。

      由于您只读取一个字节,这就足够了:

      char c;
      myfile.read(&c, 1);
      

      【讨论】:

      • std::vector 是位图数组而不是普通数组。它的尺寸类型是 std::vector::size_type 而不是 size_t
      • @larsmans 是的,但具有与普通数组不同的行为(指针 [0] 不再是第一个元素)。
      • @Ashot:我都知道。我要说明的一点是,通过将其地址转换为char *,OP 将无法通过任何std::vector 专业化获得正确的行为。是的,这是特定于实现的,但请描述 C++ 初学者也可以理解的任何其他实现 std::vector 的合理方式。
      • 我只是想做一些类似这里所做的事情:courses.cs.vt.edu/~cs2604/fall02/binio.html 在标题“读写复杂数据”下
      【解决方案5】:

      C++ 语言不提供将位读取为位的有效 I/O 方法。您必须分组读取位。此外,在读取 int 位时,您必须担心 Endianess。

      我建议分配缓冲区的老式方法,读取缓冲区然后对缓冲区进行操作。

      分配缓冲区

      const unsigned int BUFFER_SIZE = 1024 * 1024; // Let the compiler calculate it.
      //...
      unsigned char * const buffer = new unsigned char [BUFFER_SIZE];  // The pointer is constant.
      

      读入数据

      unsigned int bytes_read = 0;
      ifstream data_file("myfile.bin", ios::binary); // Open file for input without translations.
      data_file.read(buffer, BUFFER_SIZE); // Read data into the buffer.
      bytes_read = data_file.gcount();  // Get actual count of bytes read.
      

      提醒:

      • delete 缓冲区当你 完成它。
      • 完成后关闭文件 用它。

      【讨论】:

        【解决方案6】:
        myfile.read((char*) &encoded2[0], sizeof(int)* COUNT);
        

        或者你可以使用 push_back();

        int tmp;
        for(int i = 0; i < COUNT; i++) {
          myfile.read((char*) &tmp, 4);
          encoded2.push_back(tmp);
        }
        

        【讨论】:

          猜你喜欢
          • 2015-06-27
          • 2015-04-23
          • 2018-01-16
          • 1970-01-01
          • 1970-01-01
          • 2019-04-04
          • 1970-01-01
          • 2018-05-24
          • 1970-01-01
          相关资源
          最近更新 更多