【问题标题】:Extracting data from a file that was read into memory从读入内存的文件中提取数据
【发布时间】:2013-05-17 20:10:18
【问题描述】:

我有一个二进制数据文件,其中包含按以下顺序排列的 2d 和 3d 坐标:

uint32 numberOfUVvectors;
2Dvec uv[numberOfUVvectors];
uint32 numberOfPositionVectors;
3Dvec position[numberOfPositionVectors];
uint32 numberOfNormalVectors;
3Dvec normal[numberOfNormalVectors];

2Dvec 和 3Dvec 分别是由 2 个和 3 个浮点数组成的结构体。

起初,我使用“通常”的方式读取所有这些值:

in.read(reinterpret_cast<char *>(&num2d), sizeof(uint32));
2Dvectors.reserve(num2d); // It's for an std::vector<2DVec> 2Dvectors();
for (int i = 0; i < num2d; i++){
    2Dvec 2Dvector;
    in.read(reinterpret_cast<char *>(&2Dvector), sizeof(2DVec));
    2Dvectors.push_back(2Dvector);
}

它运行良好,但速度非常慢(一个文件中可能有超过 200k 的条目,并且有这么多的读取调用,硬盘访问成为瓶颈)。我决定一次将整个文件读入缓冲区:

in.seekg (0, in.end);
int length = in.tellg();
in.seekg (0, in.beg);

char * buffer = new char [length];

is.read (buffer,length);

现在读取速度更快了,但问题是:如何将该 char 缓冲区解析回整数和结构?

【问题讨论】:

    标签: c++ file stream binary


    【解决方案1】:

    回答您的具体问题:

    unsigned char * pbuffer = (unsigned char *)buffer;
    
    uint32 num2d = *((uint32 *)pbuffer);
    pbuffer += sizeof(uint32);
    if(num2d)
    {
        2Dvec * p2Dvec = (2Dvec *)pbuffer;
        2Dvectors.assign(p2Dvec, p2Dvec + num2d);
        pbuffer += (num2d * sizeof(2Dvec));
    }
    
    uint32 numpos = *((uint32 *)pbuffer);
    pbuffer += sizeof(uint32);
    if(numpos)
    {
            3Dvec * p3Dvec = (3Dvec *)pbuffer;
        Pos3Dvectors.assign(p3Dvec, p3Dvec + numpos);
        pbuffer += (numpos * sizeof(3Dvec));
    }
    
    uint32 numnorm = *((uint32 *)pbuffer);
    pbuffer += sizeof(uint32);
    if(numnorm)
    {
        3Dvec * p3Dvec = (3Dvec *)pbuffer;
        Normal3Dvectors.assign(p3Dvec, p3Dvec + numnorm);
        pbuffer += (numnorm * sizeof(3Dvec));
    }
    // do not forget to release the allocated buffer
    

    一个更快的方法是:

    in.read(reinterpret_cast<char *>(&num2d), sizeof(uint32));
    if(num2d)
    {
        2Dvectors.resize(num2d);
        2Dvec * p2Dvec = &2Dvectors[0];
        in.read(reinterpret_cast<char *>(&p2Dvec), num2d * sizeof(2Dvec));
    }
    //repeat for position & normal vectors
    

    【讨论】:

      【解决方案2】:

      使用具有适当大小和起始值的 memcpy

      或转换值(示例):

      #include <iostream>
      
      void copy_array(void *a, void const *b, std::size_t size, int amount)
      {
          std::size_t bytes = size * amount;
          for (int i = 0; i < bytes; ++i)
              reinterpret_cast<char *>(a)[i] = static_cast<char const *>(b)[i];
      }
      
      int main()
      {
          int a[10], b[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
      
          copy_array(a, b, sizeof(b[0]), 10);
      
          for (int i = 0; i < 10; ++i)
              std::cout << a[i] << ' ';
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-04-18
        • 1970-01-01
        • 1970-01-01
        • 2020-08-01
        • 1970-01-01
        • 2017-02-05
        相关资源
        最近更新 更多