簡體   English   中英

使用np.fromfile或open&struct讀取fortran二進制文件(流訪問)

[英]Reading fortran binary (streaming access) with np.fromfile or open & struct

以下Fortran代碼:

INTEGER*2 :: i, Array_A(32)
Array_A(:) = (/ (i, i=0, 31) /)

OPEN (unit=11, file = 'binary2.dat', form='unformatted', access='stream')
    Do i=1,32
        WRITE(11) Array_A(i)
    End Do 
CLOSE (11)

生成流式二進制輸出,數字從0到31,整數為16位。 每條記錄占用2個字節,因此它們寫在字節1,3,5,7等等。 access ='stream'為每條記錄抑制了Fortran的標准頭(我需要這樣做以保持文件盡可能小)。

用十六進制編輯器查看它,我得到:

00 00 01 00 02 00 03 00 04 00 05 00 06 00 07 00 
08 00 09 00 0A 00 0B 00 0C 00 0D 00 0E 00 0F 00
10 00 11 00 12 00 13 00 14 00 15 00 16 00 17 00
18 00 19 00 1A 00 1B 00 1C 00 1D 00 1E 00 1F 00

這是完全正常的(盡管從未使用過第二個字節,因為在我的例子中小數太低)。

現在我需要將這些二進制文件導入Python 2.7,但我不能。 我嘗試了很多不同的例程,但我總是這樣做。

1.嘗試: “np.fromfile”

with open("binary2.dat", 'r') as f:
    content = np.fromfile(f, dtype=np.int16)

回報

[    0     1     2     3     4     5     6     7     8     9    10    11
    12    13    14    15    16    17    18    19    20    21    22    23
    24    25     0     0 26104  1242     0     0]

2.嘗試: “struct”

import struct
with open("binary2.dat", 'r') as f:
    content = f.readlines()
    struct.unpack('h' * 32, content)

提供

struct.error: unpack requires a string argument of length 64

因為

print content
['\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08\x00\t\x00\n', '\x00\x0b\x00\x0c\x00\r\x00\x0e\x00\x0f\x00\x10\x00\x11\x00\x12\x00\x13\x00\x14\x00\x15\x00\x16\x00\x17\x00\x18\x00\x19\x00']

(請注意根據Fortran的“流媒體”訪問權限,分隔符,t和n不應該存在)

3.嘗試: “FortranFile”

f = FortranFile("D:/Fortran/Sandbox/binary2.dat", 'r')
print(f.read_ints(dtype=np.int16))

有錯誤:

TypeError: only length-1 arrays can be converted to Python scalars

(記住它是如何在文件中間檢測到分隔符的,但是對於沒有換行符的較短文件也會崩潰(例如從0到8的小數))

一些額外的想法:

Python似乎在閱讀部分二進制文件時遇到麻煩。 對於np.fromfile它讀取Hex 19 (dec:25),但是對於Hex 1A (dec:26)崩潰。 它似乎與字母混淆,雖然0A,0B ......工作得很好。

對於嘗試2, content結果很奇怪。 小數0到8工作正常,但是有一個奇怪的\\t\\x00\\n事情。 那么hex 09是什么呢?

我花了好幾個小時試圖找到邏輯,但我被困住了,真的需要一些幫助。 有任何想法嗎?

問題出在打開文件模式。 默認為'text'。 將此模式更改為二進制:

with open("binary2.dat", 'rb') as f:
    content = np.fromfile(f, dtype=np.int16)

並且所有數字都將成功加入。 有關更多詳細信息,請參閱Dive in Python章節二進制文件

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM