2

我正在读取文件 *stl 中的结构,但结构是:

typedef struct
{
    float x;
    float y;
    float z;
} point;
typedef struct 
{
    point normal_vector; //12 bytes
    point p1; //12 bytes
    point p2; //12 bytes
    point p3; //12 bytes
    short int notuse; //2 bytes
} triangle;

sizeof(triangle)是 52—12+12+12+12+2+...2 (不知道最后 2 是从哪里来的?) *stl 文件中每个单元的大小是 50(不是 4 的倍数)。

如何减小读取文件的结构大小(从 52 到 50)?

谢谢你。

4

3 回答 3

1

由于填充,额外的两个字节即将到来。填充是使结构与 4 字节边界对齐(您的字长可能是 32 位,它可能因 64 位而异)。

在文件中,您为每个结构存储了 50 个字节。因此,您可以读取这 50 个字节并将值从 50 个字节开始分配给每个成员。代码看起来像

Char readbuf[50];

//Read the 50 bytes into the buffer readbuf.

 triangle t;

 t.normal_vector.x  = (float *)readbuf;
 t.normal_vector.y  = (float *)(readbuf + sizeof(float));
 t.normal_vector.z  = (float *)(readbuf + 2*sizeof(float));
 t.p1.x             = (float *)(readbuf + 3*sizeof(float));

//and so on for other members.

请注意,这有字节对齐问题,相同的程序可能无法在大端机器上运行。因此,请注意在没有任何规则或编码的情况下直接存储二进制数据。

于 2013-11-02T09:13:34.693 回答
1

使用 GCC/G++,你可以这样做来打包你的结构:

typedef struct 
{
    point normal_vector; //12 bites
    point p1; //12 bites
    point p2; //12 bites
    point p3; //12 bites
    short int notuse; //2 bites
} __attribute__((packed)) triangle;
于 2013-11-02T09:16:32.837 回答
1

一种比阅读结构更受欢迎的方法 - 如您所见,其内存布局可能会有所不同 - 按原样减少其大小可能是可行的方法。

也就是说,您可以大块读取文件并在需要的部分中剪切数据。然后你读出一个字段一个字段并将数据放入你的目标数组中。就像是

float read_float(void ** data) {
    float ** fp = data;
    float ret = **fp; (*fp)++;
    return ret;
}

point read_point(void ** data) {
    point ret;
    ret.x = read_float(data);
    ret.y = read_float(data);
    ret.z = read_float(data);
    return ret;
}

int16_t read16(void ** data) {
    int16_t ** i16p = data;
    int16_t ret = **i16p; (*i16p)++;
    return ret;
}

point read_triangle(void ** data) {
    triangle ret;
    ret.normal_vector = read_point(data);
    ret.p1 = read_point(data);
    ret.p2 = read_point(data);
    ret.p3 = read_point(data);
    ret.notuse = read_int16(data); // using short int is not portable as well as its size could vary...
    return ret;
}

void * scursor = source_array; // which would be a char array
while (scursor < source_array + sizeof(source_array)) {
    // make sure that there are enough data present...
    target[tcursor++] = read_triangle(&scursor); // the scursor will be advanced by the called function.
}

这种方式也可以 - 通过某些增强 - 用于保持例如数字的字节序相同 - 在旨在在平台之间交换的文件上最好是大字节序。更改read16会很小,更改会read_float更大一些,但仍然可行。

于 2013-11-02T09:22:44.487 回答