C++ 从硬盘读取dosen';不遵循计算机字节对齐

C++ 从硬盘读取dosen';不遵循计算机字节对齐,c++,performance,file-io,C++,Performance,File Io,我有一个文件格式(.STL,立体光刻,结构是标准的,不能更改。不要与标准模板库混淆)使用50字节的数据结构。由于50字节不是4的倍数,因此从HD读取数据会直接导致读取错误数据 在整个50字节的结构中,我只需要36个字节。我现在用来提取数据的方法是手动将文件的读取位置偏移到下一组数据开始的位置,将36个字节读入一个临时变量,然后将临时变量中的数据转储到数组中的适当位置 下面是代码块: threePoints* output = new threePoints [numTriangles]; //

我有一个文件格式(.STL,立体光刻,结构是标准的,不能更改。不要与标准模板库混淆)使用50字节的数据结构。由于50字节不是4的倍数,因此从HD读取数据会直接导致读取错误数据

在整个50字节的结构中,我只需要36个字节。我现在用来提取数据的方法是手动将文件的读取位置偏移到下一组数据开始的位置,将36个字节读入一个临时变量,然后将临时变量中的数据转储到数组中的适当位置

下面是代码块:

threePoints* output = new threePoints [numTriangles]; // create an array to hold the entire file
threePoints* temp = new threePoints [1]; // temp variable to pull data out of each "cell"

// extract each triangle individualy
for (int i = 0; i < numTriangles; i++)
{
    stlFile.seekg (96 + i * 50, ios::beg);  //read vertex data and put them into tempoary array
                                            // offset = 80 header + 4 #triangles + 12 normal vector
    stlFile.read(reinterpret_cast<char*>(temp), (36)); // read the next 36 data blocks into holder, 3 points * 3 axis * 4 bytes per float
    output[i] = temp[0]; // dump values in holder into proper array
}
threePoints*输出=新的三点[numTriangles];//创建一个数组来保存整个文件
三点*温度=新的三点[1];//用于从每个“单元”中提取数据的临时变量
//单独提取每个三角形
对于(int i=0;i
这种方法有效,但速度很慢。我该如何做才能让它更快、更有效


编辑:我知道手动禁用字节对齐可以解决这个问题,但我需要大量使用生成的数组并对其进行多次迭代。有人告诉我,禁用字节对齐可能会导致性能问题,因此我避免了它。

与其进行一系列小的查找和读取,不如分配一个大的缓冲区(比如,足以容纳1000个结构),然后一次读取一组记录。(然后重复该缓冲区,复制出所需的36字节块)。

与其进行一系列小的查找和读取,不如分配一个大的缓冲区(例如,足以容纳1000个结构),然后一次读取一组记录。(然后遍历该缓冲区,复制出所需的36字节块)。

将结构定义括在
#pragma pack(1,push)
#pragma pack(pop)
中。大多数编译器都支持这一点。然后不应添加自动填充


该软件声称它是微软的一项兼容性功能,但它已经存在了很久……可能比GCC本身的时间更长。

将结构定义括在
#pragma pack(1,push)
#pragma pack(pop)
中。大多数编译器都支持这一点。然后不应添加自动填充


该软件声称它是微软的一项兼容性功能,但它已经存在了很久……可能比GCC本身的时间更长。

我没有STL数据可供测试,但类似这样的东西怎么样

#include <fstream>

#pragma pack(push, 1)

struct stl_hdr {
   unsigned int header[80];
   unsigned int triangle_cnt;
};

struct triangle {
   float norm;
   float v1;
   float v2;
   float v3;
   short attr_cnt;
};

#pragma pack(pop)

using namespace std;

int main(int argc, char* argv[]) {
   ifstream file(argv[1], ios::in | ios::binary);

   if (file.is_open()) {
      stl_hdr hdr;
      file.read((char*)&hdr, sizeof(hdr));

      triangle* tris = new triangle[hdr.triangle_cnt];

      file.read((char*)tris, hdr.triangle_cnt * sizeof(triangle));

      file.close();
   }

   return 0;
}
#包括
#pragma包(推送,1)
结构stl_hdr{
无符号整数头[80];
无符号整数三角形;
};
结构三角形{
浮动范数;
浮动v1;
浮动v2;
浮动v3;
短属性;
};
#布拉格语包(流行语)
使用名称空间std;
int main(int argc,char*argv[]){
ifstream文件(argv[1],ios::in | ios::binary);
if(file.is_open()){
stl_hdr hdr;
read((char*)&hdr,sizeof(hdr));
三角形*tris=新三角形[hdr.三角形_cnt];
read((char*)tris,hdr.triangle_cnt*sizeof(triangle));
file.close();
}
返回0;
}

我基于创建了两个结构。上面的代码做了与您的代码相同的假设…属性计数为零。我省略了错误处理/清理。

我没有STL数据可供测试,但像这样的东西怎么样

#include <fstream>

#pragma pack(push, 1)

struct stl_hdr {
   unsigned int header[80];
   unsigned int triangle_cnt;
};

struct triangle {
   float norm;
   float v1;
   float v2;
   float v3;
   short attr_cnt;
};

#pragma pack(pop)

using namespace std;

int main(int argc, char* argv[]) {
   ifstream file(argv[1], ios::in | ios::binary);

   if (file.is_open()) {
      stl_hdr hdr;
      file.read((char*)&hdr, sizeof(hdr));

      triangle* tris = new triangle[hdr.triangle_cnt];

      file.read((char*)tris, hdr.triangle_cnt * sizeof(triangle));

      file.close();
   }

   return 0;
}
#包括
#pragma包(推送,1)
结构stl_hdr{
无符号整数头[80];
无符号整数三角形;
};
结构三角形{
浮动范数;
浮动v1;
浮动v2;
浮动v3;
短属性;
};
#布拉格语包(流行语)
使用名称空间std;
int main(int argc,char*argv[]){
ifstream文件(argv[1],ios::in | ios::binary);
if(file.is_open()){
stl_hdr hdr;
read((char*)&hdr,sizeof(hdr));
三角形*tris=新三角形[hdr.三角形_cnt];
read((char*)tris,hdr.triangle_cnt*sizeof(triangle));
file.close();
}
返回0;
}

我基于创建了两个结构。上面的代码做了与您的代码相同的假设…属性计数为零。我省略了错误处理/清理。

我关心的是稍后迭代结构数组时的性能。我密集使用这个阵列,速度很重要。上次有人告诉我,禁用字节对齐会严重影响性能。@Faken:另一方面,扩展数组的总大小,甚至只复制一次也会影响性能。偏差惩罚也可能非常小。我建议两种方法都试一下。我关心的是以后遍历结构数组时的性能。我密集使用这个阵列,速度很重要。上次有人告诉我,禁用字节对齐会严重影响性能。@Faken:另一方面,扩展数组的总大小,甚至只复制一次也会影响性能。偏差惩罚也可能非常小。我建议两种方法都试一下。回答得好。问题不是没有对齐,问题是做了一堆冗余的读取请求。我该如何直接从硬盘读取一块数据到内存中,然后删除不必要的部分?如果可能的话,我想这个问题真的不是问题,因为我不知道该怎么做。读入
char
缓冲区。缓冲区中第N条记录的位置是buf+(50*N),因此如果您的结构与磁盘上的对齐方式匹配,则可以说
输出[i]=*(reinterpret_cast(buf+(50*N));