读取C中使用Python结构编写的二进制数据

时间:2013-12-02 17:19:10

标签: python c io

我正在用Python编写一个二进制文件,用C语言读取。编写该文件的(MWE)代码是:

import struct

with open('test.bin', 'wb') as outfile:  
    outfile.write(struct.pack('didi', 1.2, 1, 1.3, 2))

当我用C读取文件时,我收到乱码数据:

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

int main(int argc, char *argv[]) {
    double testdouble, testdoubletwo;
    int testint, testinttwo;

    FILE *f = fopen("test.bin", "rb");
    assert(f);

    assert(fread(&testdouble, sizeof(testdouble), 1, f));
    assert(fread(&testint, sizeof(testint), 1, f));
    assert(fread(&testdoubletwo, sizeof(testdoubletwo), 1, f));
    assert(fread(&testinttwo, sizeof(testinttwo), 1, f));

    fprintf(stderr, "testdouble: %f, testint: %d, testdouble: %f, testinttwo: %d", testdouble, testint, testdoubletwo, testinttwo);

    return 0;
}

输出:

testdouble: 1.200000, testint: 1, testdouble: -92559641157289301412905710012271939667257667601819249288413184.000000, testinttwo: 1073007820

如果我省略整数,它适用于这个小例子,但不适用于我正在阅读几十个双打的实际问题。其中一些(不是第一个,而不是最后一个)最终会出现乱码。

系统:Ubuntu 12.04,64位
Python:2.7.3

2 个答案:

答案 0 :(得分:1)

在您的C代码中,您逐个读取每个项目,这意味着您没有应用任何对齐。试试这个:

outfile.write(struct.pack('=didi', 1.2, 1, 1.3, 2))

hexdump test.bin

0000000 3333 3333 3333 3ff3 0001 0000 cccd cccc
0000010 cccc 3ff4 0002 0000                    

C代码输出:

testdouble: 1.200000, testint: 1, testdouble: 1.300000, testinttwo: 2

如果你不改变python代码,仍然使用'didi',然后像这样更改c代码:

struct D {
    double td;
    int ti;
    double td2;
   int ti2;
};


struct D d;
fread(&d, sizeof(struct D), 1, f);
fprintf(stderr, "testdouble: %f, testint: %d, testdouble: %f, testinttwo: %d", d.td, d.ti, d.td2, d.ti2);

这个测试在Fedora 17上,使用python 2.7.3,gcc 4.7.2,我更喜欢定义结构。

答案 1 :(得分:0)

我还应该说可以更改C程序而不是python程序。这几乎是完美的,除了在我的系统上python写了一个28字节的文件,而我的C程序需要32个字节。它没有断言。不理想。在testinttwo之后写一个垃圾int可以解决这个问题。

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

int main(int argc, char *argv[]) {
    typedef struct { double testdouble;
                     int testint;
                     double testdoubletwo;
                     int testinttwo;
                } teststruct;
    teststruct abc;
    FILE *f = fopen("test.bin", "rb");
    assert(f);
/*  assert(fread(&abc, sizeof(teststruct), 1, f));*/
    printf("sizeof(teststruct) %d\n",sizeof(teststruct));
    fread(&abc, sizeof(teststruct), 1, f);

    fprintf(stderr, "testdouble: %f, testint: %d, testdouble: %f, testinttwo: %d", abc.testdouble, abc.testint, abc.testdoubletwo, abc.testinttwo);

    return 0;
}

调整后的python程序来解决断言问题。

import struct

with open('test.bin', 'wb') as outfile:
    outfile.write(struct.pack('didii', 1.2, 1, 1.3, 2,0))

C输出:

sizeof(teststruct) 32
testdouble: 1.200000, testint: 1, testdouble: 1.300000, testinttwo: 2