2012-01-03 161 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 2012-01-03 10:02:46

+1

請忽略我之前的評論,整數8和4 * N顯然是這些額外的數據。 – Chris 2012-01-03 10:43:33

+2

此外,請參閱問題的答案[在Python中讀取二進制文件](http://stackoverflow.com/questions/1035340/reading-binary-file-in-python)。 – Chris 2012-01-03 10:46:53

回答

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:不支持的操作數類型(s)//:'str'和'int'。在閱讀我的文件的主體時,能否更好地解釋我的代碼的含義? – Brian 2012-01-03 11:08:21

+0

一些括號丟失。我更新了我的帖子 – gecco 2012-01-03 11:10:28

+0

我想通了我自己!非常感謝非常有幫助的答案! – Brian 2012-01-03 11:19:58

21

一般來說,我建議你看看Python的struct模塊。它是Python的標準,應該很容易將您的問題規範轉換爲適合於struct.unpack()的格式化字符串。

請注意,如果字段之間/周圍存在「不可見」填充,則需要計算出該字段並將其包含在unpack()調用中,否則您將讀取錯誤的位。

讀取文件的內容,以有東西來解壓是很簡單的:

import struct 

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

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

這拆包前兩個字段,假設他們開始在文件(沒有填充或外來的開始數據),並且還假定本地字節順序(@符號)。格式化字符串中的I表示「無符號整數,32位」。

+0

好的,但我甚至不知道如何讀取文件的字節。從我的問題我怎麼能讀取從字節5到8的文件,然後將結果轉換爲一個整數?對不起,但我是Python新手。 – Brian 2012-01-03 10:39:23

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 2017-03-23 10:55:49

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

可能值得一點解釋爲什麼這比其他答案更好(或至少一樣好)。 – Phil 2017-12-13 16:38:10

+1

您是否測試了驗證過的Fortran生成的二進制文件? – agentp 2017-12-13 17:14:56

+0

也解釋它是做什麼的...什麼是泡菜? pickle.load負載是什麼?它是否加載Fortran流,直接或順序文件?他們是不同的,不兼容。 – 2017-12-13 19:37:40