2012-01-03 22 views
60

Pythonで特に読みにくいバイナリファイルが見つかりました。手伝って頂けますか? 私は、Fortran 90で簡単に詳細にPythonでバイナリファイルを読む

int*4 n_particles, n_groups 
real*4 group_id(n_particles) 
read (*) n_particles, n_groups 
read (*) (group_id(j),j=1,n_particles) 

によって読み取られ、このファイルを、読む必要が、ファイル形式は次のとおりです。

Bytes 1-4 -- The integer 8. 
Bytes 5-8 -- The number of particles, N. 
Bytes 9-12 -- The number of groups. 
Bytes 13-16 -- The integer 8. 
Bytes 17-20 -- The integer 4*N. 
Next many bytes -- The group ID numbers for all the particles. 
Last 4 bytes -- The integer 4*N. 

は、どのように私は、Pythonでこれを読むことができますか?私はすべてを試みたが、それは決して働かなかった。私はPythonでこのバイナリファイルを読んで、私が使用する必要があるデータを保存するf90プログラムを使用する可能性はありますか?

+1

このファイルは、Fortranプログラムによって書かれましたか?そうであれば、Fortranはデフォルトで、ファイルに書き込む各レコードの前に追加のデータを追加するので、どのように書かれましたか?データを読むときは、このことに注意する必要があります。 – Chris

+1

私の以前のコメントを無視してください、intergers 8と4 * Nは明らかにこの追加のデータです。 – Chris

+2

また、[バイナリファイルをPythonで読む](http://stackoverflow.com/questions/1035340/reading-binary-file-in-python)の回答を参照してください。 – Chris

答えて

79

読むこのようなバイナリファイルの内容:

with open(fileName, mode='rb') as file: # b is important -> binary 
    fileContent = file.read() 

その後、struct.unpackを使用してバイナリデータを "解凍":

開始バイト:struct.unpack("iiiii", fileContent[:20])

ボディ:見出しのバイトを無視して、末尾のバイト(= 24)。残りの部分はボディのバイト数を知るためにボディを形成し、4で整数除算を行います。得られる商はアンパック方法の正しい形式を作成するために、文字列'i'を乗じて:

struct.unpack("i" * ((len(fileContent) -24) // 4), fileContent[20:-4]) 

エンド・バイト:struct.unpack("i", fileContent[-4:])

+0

ありがとうございますが、あなたのコードでは、開始と終了のバイトを読み取ることはできますが、本文は読み取ることはできません。このエラーメッセージが表示されます。TypeError://: 'str'と 'int'のサポート対象外のオペランドタイプです。私のファイルの本文を読むときにコードの意味をよりよく説明できますか? – Brian

+0

カッコがいくつか見つかりませんでした。私は自分の投稿を更新しました – gecco

+0

私は自分で考え出しました!非常に有益な答えをありがとう! – Brian

21

一般的に、これはPythonのstructモジュールを使用して調べることをお勧めします。これはPythonの標準であり、質問の仕様をstruct.unpack()に適した書式設定文字列に変換するのは簡単です。

フィールド間に「見えない」パディングがある場合は、それを把握してunpack()コールに含めるか、間違ったビットを読み込む必要があります。解凍するために何かを持っているために、ファイルの内容を読み込む

は非常に簡単です:

import struct 

data = open("from_fortran.bin", "rb").read() 

(eight, N) = struct.unpack("@II", data) 

これは、彼らがファイル(なしパディングまたは余分の先頭に開始すると仮定すると、最初の2つのフィールドをアンパックデータ)、およびネイティブバイトオーダー(@シンボル)を前提としています。書式化文字列のIは、「符号なし整数、32ビット」を意味します。

+0

でも、ファイルのバイトを読み取る方法はわかりません。私の質問から、バイト5から8までのファイルをどのように読み込み、その結果を整数に変換できますか?申し訳ありませんが、私はPythonの新機能です。 – Brian

8

numpy.fromfileを使用すると、テキストファイルとバイナリファイルの両方からデータを読み取ることができます。最初に、numpy.dtypeを使用してファイル形式を表すデータ型を作成し、numpy.fromfileを使用してファイルからこの型を読み取ります。

+0

これを見逃しやすい!ドキュメントは少し薄いです。いくつかの議論については、https://www.reddit.com/r/Python/comments/19q8nt/psa_consider_using_numpy_if_you_need_to_parse_a/を参照してください。 – lost

-1
import pickle 
f=open("filename.dat","rb") 
try: 
    while True: 
     x=pickle.load(f) 
     print x 
except EOFError: 
    pass 
f.close() 
+5

おそらくこれが他の答えより優れている理由(あるいは少なくとも少なくとも良い点)について少し説明する価値があるでしょう。 – Phil

+1

Fortranで生成されたバイナリで動作確認済みですか? – agentp

+0

また、それが何をしているのかを説明してください...ピクルスとは何ですか? 'pickle.load'は何をロードしますか? Fortranストリーム、直接ファイルまたは順次ファイルをロードしますか?彼らは異なっていて互換性がありません。 –

関連する問題