从Python中解析用MATLAB编写的二进制文件,反之亦然

时间:2016-08-21 09:03:07

标签: python matlab file struct binary

我在python中遇到struct.unpack的主要问题。我有一个预定格式的二进制文件,可以用MATLAB或Python编写。

我可以用Python将二进制数据写入文件,并且可以毫无问题地读回数据。我也可以将相同的数据写入MATLAB的二进制文件,并在MATLAB中读回来没有问题。

当我从MATLAB写入数据并尝试用Python读取数据,或者用Python编写数据并尝试在MATLAB中读取数据时,我的问题出现了。

为简单起见,我们假设我将两个整数写入二进制文件(big-endian)。每个整数是4个字节。第一个整数是一个不大于4个字节的有效整数,第二个整数必须等于1,2或3。

首先,这是我在MATLAB中编写数据的方法:

fid=fopen('hello_matlab.test','wb');
first_data=4+4;
second_data=1;

fwrite(fid,first_data,'int');
fwrite(fid,second_data,'int');

fclose(fid);

以下是我在MATLAB中阅读的内容:

fid=fopen('hello_matlab.test','rb');
first_data=fread(fid,1,'int');
second_data=fread(fid,1,'int');

fprintf('first data: %d\n', first_data);
fprintf('second data: %d\n', second_data);

fclose(fid);

    >> first data: 8
    >> second data: 1

现在,我在这里用Python编写数据:

fid=open('hello_python.test','wb')
first_data=4+4
second_data=1

fid.write(struct.pack('>i',first_data))
fid.write(struct.pack('>i',second_data))

fid.close()

以下是我在python中读取数据的方法。另请注意,注释掉的部分有效(当读取用Python编写的文件时)。我原本以为计算struct.calcsize('>i')的方式发生了一些奇怪的事情,所以我删除了它,而是放了一个硬编码常量INTEGER_SIZE来表示我知道MATLAB使用的字节数。编码:

INTEGER_SIZE=4

fid=open('hello_python.test','rb')

### FIRST WAY I ORIGINALLY READ THE DATA ###
# This works, but I figured I would try hard coding the size
# so the uncommented version is what I am currently using.
#
# first_data=struct.unpack('>i',fid.read(struct.calcsize('>i')))[0]
# second_data=struct.unpack('>i',fid.read(struct.calcsize('>i')))[0]

### HOW I READ DATA CURRENTLY ###
first_data=struct.unpack('>i',fid.read(INTEGER_SIZE))[0]
second_data=struct.unpack('>i',fid.read(INTEGER_SIZE))[0]

print "first data: '%d'" % first_data
print "second data: '%d'" % second_data

fid.close()

    >> first data: 8
    >> second data: 1

现在,我想在MATLAB中阅读hello_python.test。使用我当前的MATLAB代码,这是新输出:

>> first data: 419430400
>> second data: 16777216

这很奇怪,所以我做了相反的事情。我看了看hello_matlab.test时会发生什么。使用我当前的Python代码,这是新输出:

>> first data: 419430400
>> second data: 16777216

所以,有些奇怪的事情正在发生,但我不知道它是什么。另请注意,虽然这是大型项目的一部分,但我只是将我的代码的这些部分提取到一个新项目中,并使用这些结果测试上面的示例。我真的很困惑如何使这个文件可移植:(任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:1)

您可能对pandas hdf5商店感兴趣:

在Python中:

 public class MainActivity extends Activity {
    TextView txtview;
    EditText edttxt;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        txtview=(TextView)findViewById(R.id.textView);
    edttxt=(EditText)findViewById(R.id.edittxt);

    String no=edttxt.getText().toString();       //this will get a string
    int no2=Integer.parseInt(no);              //this will get a no from the string

    Button btn=(Button)findViewById(R.id.btn);
    btn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            txtview.setText(edttxt.getText());
        }
    });

}
}

在matlab中:

In [418]: df_for_r = pd.DataFrame({"first": np.random.rand(100),
   .....:                          "second": np.random.rand(100),
   .....:                          "class": np.random.randint(0, 2, (100,))},
   .....:                          index=range(100))
   .....: 

In [419]: df_for_r.head()
Out[419]: 
   class     first    second
0      0  0.417022  0.326645
1      0  0.720324  0.527058
2      1  0.000114  0.885942
3      1  0.302333  0.357270
4      1  0.146756  0.908535

In [420]: store_export = HDFStore('export.h5')

In [421]: store_export.append('df_for_r', df_for_r)

In [422]: store_export
Out[422]: 
<class 'pandas.io.pytables.HDFStore'>
File path: export.h5
/df_for_r            frame_table  (typ->appendable,nrows->100,ncols->3,indexers->[index])

但我不确定它是否有效,完全在浏览器中写道......

答案 1 :(得分:1)

问题在于endianness,即数字中位的顺序。您必须使用x86或x86-64计算机(因为这些是MATLAB支持的唯一计算机),并且这些是little-endian。但是,python >i告诉它使用big-endian字节顺序。所以你正在使用相反的字节顺序,这使得两种语言读出完全不同的数字。

如果您只打算在x86或x86-64计算机上使用Python代码,或者只关心在同一台计算机上在MATLAB和Python之间发送数据,那么您可以完全省略字节顺序标记,使用本机字节顺序(所以i而不是>i)。如果您可能在powerpc系统上运行python,则可能需要手动指定little-endianess(<i)。

对于这个例子,这似乎是唯一的问题。我想指出的是,如果您尝试一次读取和写入数据的数组/矩阵,那么numpy.fromfile将更快更容易。