2016-08-21 6 views
0

私はstruct.unpackで大きな問題を抱えています。私は、MATLABまたはPythonで書かれた、あらかじめ決められたフォーマットのバイナリファイルを持っています。PythonからMATLABで書かれたバイナリファイルの解析(その逆)

バイナリデータをPythonでファイルに書き込んで、問題なくデータを読み戻すことができます。同じデータをMATLABのバイナリファイルに書き込んでMATLABで問題なく読み込むこともできます。

MATLABからデータを書き込んで、Pythonでデータを読み込もうとするとき、またはPythonでデータを書き込んでMATLABで読み返すときに問題が発生します。

簡単にするために、2つの整数をバイナリファイル(ビッグエンディアン)に書き込んでいます。各整数は4バイトです。最初の整数は、4バイトを超える有効でない整数であり、2番目の整数のいずれか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); 

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でデータを書き込む方法をここでは、今

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 

です:

そして、ここでは、私はMATLABでその背中を読む方法です

そしてここで私はそのデータをどのようにしてPythonで読むのですか?また、コメントアウトされた部分は機能しました(Pythonで書かれたファイルを読むとき)。私はもともと奇妙な何かがstruct.calcsize('>i')が計算されていた方法で起こっていたと思ったので、私はそれを削除し、代わりに入れて、ハードコードされ、私はそれをエンコードする際にMATLABを使用していた知っていたバイトの量を表すために、INTEGER_SIZE、定数:

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 

ここで、hello_python.testをMATLABで読みたいとします。私の現在のMATLABコードでは、新しい出力は次のようになります。

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

これは奇妙なので、私はその逆でした。私はhello_matlab.testを読むと何が起こるかを見ました。私の現在のPythonのコードでは、ここに新しい出力がある:だから

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

、奇妙な何かが起こっているが、私はそれが何であるかを知りません。また、これは大きなプロジェクトの一部ですが、私はコードのこれらの部分を新しいプロジェクトに抽出し、上記の例をこれらの結果でテストしました。私は、このファイルがポータブルにする方法については本当に困惑している:(任意の助けいただければ幸い

+0

ビッグエンディアン形式で値を書き込んでいることを示すMATLABコードには何も表示されません。私は彼らがリトルエンディアン形式で書かれていると思われます。だから、Pythonコードを読むときは、 '

+0

また、MATLABファイル全体を書き込んだ後、そのファイルをPythonで開き、内容全体を読むための簡単な 'fid.read()'を実行した結果はどうですか? –

+0

これは役に立ちますか? http://stackoverflow.com/questions/874461/read-mat-files-in-python – cdarke

答えて

1

問題はendiannessであり、数字のビットの順序です。MATLABがサポートしているのはx86またはx86-64コンピュータでなければなりません。それらはlittle-endianです。しかし、Python >iはビッグエンディアンのバイトオーダーを使用するように指示しています。したがって、逆のバイトオーダーを使用しているため、2つの言語が完全に異なる数字を読み取るようになります。

x86またはx86-64コンピュータでPythonコードを使用する予定がある場合、または同じコンピュータ上のMATLABとPython間でデータを送信するだけの場合は、バイトオーダーマークを完全に残すことができますネイティブのバイトオーダーを使用してください(>iの代わりにi)。 powerpcシステムでpythonを実行している場合は、リトルエンディアン(<i)を手動で指定することができます。

この例では、唯一の問題です。データの配列/行列を読み書きしようとすると、numpy.fromfileがずっと速くて簡単になることを指摘したいと思います。

+0

numpyでnp.loadtxtを使用しないでください。速度で見ると、np.fromfile> np.load> pd.read_csv >> np.loadtxt(http://softwarerecs.stackexchange.com/questions/7463/fastest-python-library-to-read-aに基づいています) -csv-ファイル)。 –

+0

この問題はエンディアンに関連しているようです。私はもともと、MATLABが 'fwrite(...、 'int') 'を指定することは' int = 4 bytes'を意味しているので、それは大丈夫だろうと思っていました。しかし、 'ieee-be 'フォーマッタを追加した後、問題を解決するように見えました。 – Alex

+0

@Alex:なぜビッグエンディアンにしたいですか?あなたが最近使用しているほとんどのコンピュータはリトルエンディアンでデュアルエンディアンなので、データをビッグエンディアンにすることで不必要なオーバーヘッドを追加するだけです。 – TheBlackCat

1

あなたはHDF5店パンダにintrestedてすることができる:Pythonで

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]) 
MATLABで

data = h5read('export.h5','/df_for_r'); 

しかし、イムそれが動作するかどうかわからない、ブラウザで完全に書いた...

+0

私たちはもともとnetcdfを使用しており、比較的独立した言語になるように独自のバイナリファイル形式に移行したいと思っていました。(残念ながら私は – Alex

+0

C++で作成するのはどうでしょうか?cでデータを書き留めて保存し、それを保存して、c、putで読み込みますどこかelese?Cは普遍的だと思う...私はその話題で遊んでいないが、私はそれをcから始めるだろう:)簡単なcsvファイルを使うのが最も簡単だろう...ストレージキャップで最も効率的なのはpandas hdf5圧縮で保存する...最も効率的なスピードで私はdknow xD ... –

+0

ええと、私は自分自身で問題を解決し、Cでそれを書くことができると思う。 – Alex

関連する問題