3

FORTRAN コードからのバイナリ出力ファイルがあります。Pythonで読みたい。(FORTRAN で読み取り、Python で読み取るテキストを出力することはオプションではありません。長い話です。) 最初のレコードを単純な方法で読み取ることができます。

>>> binfile=open('myfile','rb')
>>> pad1=struct.unpack('i',binfile.read(4))[0]
>>> ver=struct.unpack('d',binfile.read(8))[0]
>>> pad2=struct.unpack('i',binfile.read(4))[0]
>>> pad1,ver,pad2
(8,3.13,8)

大丈夫です。しかし、これは大きなファイルであり、これをより効率的に行う必要があります。だから私は試します:

>>> (pad1,ver,pad2)=struct.unpack('idi',binfile.read(16))

これは実行されません。エラーが表示され、unpack には長さ 20 の引数が必要であることが通知されます。これは、最後にチェックしたとき (4+8+4=16) 以来、意味がありません。あきらめて 16 を 20 に置き換えると、実行されますが、3 つの数字には数字のジャンクが取り込まれます。誰かが私が間違っていることを見ていますか? ありがとう!

4

3 に答える 3

6

このstructモジュールは、主に C 構造体との相互運用を目的としており、そのためデータ メンバーを整列させます。idi次の C 構造体に対応します。

struct
{
   int int1;
   double double1;
   int int2;
}

doubleほとんどの CPU ロード操作で効率的に (または正しく) 機能するには、エントリに 8 バイトのアラインメントが必要です。int1そのため、との間に 4 バイトのパディングが追加されdouble1、構造体のサイズが 20 バイトに増加します。(リトル エンディアン マシンの場合) または(ビッグ エンディアン マシンの場合) を追加するか、単にフォーマット文字列の先頭にstructパディングを抑制しない限り、同じパディングがモジュールによって実行されます。<>=

>>> struct.unpack('idi', d)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
struct.error: unpack requires a string argument of length 20
>>> struct.unpack('<idi', d)
(-1345385859, 2038.0682530887993, 428226400)
>>> struct.unpack('=idi', d)
(-1345385859, 2038.0682530887993, 428226400)

(dはランダムな 16 文字の文字列です。)

于 2012-12-05T17:23:27.967 に答える
6

struct.calcsize('idi')表示されるサイズは位置合わせによるものです。位置合わせ後にサイズが実際に 20 であることを確認してください。アライメントなしでネイティブのバイト順を使用するには、struct.calcsize('=idi')それを指定して例に合わせます。

structモジュールの詳細については、 http://docs.python.org/2/library/struct.htmlを確認してください。

于 2012-12-05T17:13:39.060 に答える
1

UNFORMATTED、SEQUENTIAL で FORTRAN によって書き込まれたファイルを読み取るには、配列を使用することをお勧めします。

配列を使用した具体的な例は次のとおりです。

import array
binfile=open('myfile','rb')
pad = array.array('i')
ver = array.array('d')
pad.fromfile(binfile,1)   # read the length of the record 
ver.fromfile(binfile,1)   # read the actual data written by FORTRAN
pad.fromfile(binfile,1)   # read the length of the record

非常に一般的な、整数と倍精度の配列を書き込む FORTRAN レコードがある場合、Python は次のようになります。

import array
binfile=open('myfile','rb')
pad = array.array('i')
my_integers = array.array('i')
my_floats = array.array('d')
number_of_integers = 1000 # replace with how many you need to read
number_of_floats = 10000 # replace with how many you need to read
pad.fromfile(binfile,1)   # read the length of the record
my_integers.fromfile(binfile,number_of_integers) # read the integer data
my_floats.fromfile(binfile,number_of_floats)     # read the double data
pad.fromfile(binfile,1)   # read the length of the record

最後のコメントは、ファイルに文字がある場合、それらを配列に読み込んでから文字列にデコードできることです。このようなもの:

import array
binfile=open('myfile','rb')
pad = array.array('i')
my_characters = array.array('B')
number_of_characters = 63 # replace with number of characters to read
pad.fromfile(binfile,1)   # read the length of the record 
my_characters.fromfile(binfile,number_of_characters ) # read the data
my_string = my_characters.tobytes().decode(encoding='utf_8') 
pad.fromfile(binfile,1)   # read the length of the record
于 2016-03-05T22:26:15.310 に答える