2016-05-30 233 views
2

我想從下面的Fortran代碼讀取二進制文件輸出,但結果與輸出文件不一樣。Python讀取Fortran二進制文件

Fortran 77的代碼:

program test 
    implicit none 
    integer i,j,k,l 
    real*4  pcp(2,3,4) 
    open(10, file='pcp.bin', form='unformatted') 
    l = 0 
    do i=1,2 
     do j=1,2 
     do k=1,2 
      print*,k+l*2 
      pcp(i,j,k)=k+l*2 
      l = l + 1 
     enddo 
     enddo 
    enddo 
    do k=1,4 
     write(10)pcp(:,:,k) 
    enddo 
    close(10) 
    stop 
    end 

我嘗試使用下面的Python代碼:

from scipy.io import FortranFile 
f = FortranFile('pcp.bin', 'r') 
a = f.read_reals(dtype=float) 
print(a) 
+0

[讀取在Python中直接訪問fortran未格式化文件]可能重複(http://stackoverflow.com/questions/10475839/reading-a-direct-access-fortran-unformatted-file-in-python) –

+0

可能複製[Python:閱讀Fortran二進制文件使用numpy或scipy](http://stackoverflow.com/questions/30307305/python-reading-fortran-binary-file-using-numpy-or-scipy) – glls

+0

謝謝你們,但我嘗試兩種解決方案。在我的Fortran代碼中有一個3d變量和真正的* 4精度。 – marcelorodrigues

回答

2

因爲你在一個連續的文件中寫入real*4數據,只是一味在read_reals更換dtype=floatdtype='float32'(或dtype=np.float32)() :

>>> from scipy.io import FortranFile 
>>> f = FortranFile('pcp.bin', 'r') 
>>> print(f.read_reals(dtype='float32')) 
[ 1. 9. 5. 13. 0. 0.] 
>>> print(f.read_reals(dtype='float32')) 
[ 4. 12. 8. 16. 0. 0.] 
>>> print(f.read_reals(dtype='float32')) 
[ 0. 0. 0. 0. 0. 0.] 
>>> print(f.read_reals(dtype='float32')) 
[ 0. 0. 0. 0. 0. 0.] 

獲得的數據分別對應於0在Fortran語言,如驗證通過

do k=1,4 
    print "(6f8.3)", pcp(:,:,k) 
enddo 

這給(與pcp初始化爲零)

1.0 9.0 5.0 13.0 0.0 0.0 
    4.0 12.0 8.0 16.0 0.0 0.0 
    0.0 0.0 0.0 0.0 0.0 0.0 
    0.0 0.0 0.0 0.0 0.0 0.0 

但由於>>> help(FortranFile)

Fortran中一個未格式化的順序文件的一個例子是寫成::

OPEN(1, FILE=myfilename, FORM='unformatted')

WRITE(1) myvariable

由於這是一個非標準的文件格式,其內容取決於 編譯器和機器的字節順序,謹慎建議。來自 的文件知道x86_64上的gfortran 4.8.0和gfortran 4.1.2可以正常工作。

考慮使用Fortran直接訪問文件或來自較新Stream I/O的文件,這些文件可以通過numpy.fromfile輕鬆讀取。

根據情況使用numpy.fromfile()可能會更簡單(如StanleyR的答案所示)。

1

使用nupy.fromfile(http://docs.scipy.org/doc/numpy/reference/generated/numpy.fromfile.html

我想你錯過了什麼在Fortran代碼中,寫入二進制文件應用此代碼:

program test 
implicit none 
integer i,j,k,l, reclen 
real*4  pcp(2,3,4) 

inquire(iolength=reclen)pcp(:,:,1) 
open(10, file='pcp.bin', form='unformatted', access = 'direct', recl = reclen) 
pcp = 0 
l = 0 
do i=1,2 
do j=1,2 
do k=1,2 
    print*,i,j,k,k+l*2 
    pcp(i,j,k)=k+l*2 
    l = l + 1 
enddo 
enddo 
enddo 
do k=1,4 
    write(10, rec=k)pcp(:,:,k) 
enddo 
close(10) 
end 

要由蟒蛇讀文件:

import numpy as np 
with open('pcp.bin','rb') as f: 
    for k in xrange(4): 
     data = np.fromfile(f, dtype=np.float32, count = 2*3) 
     print np.reshape(data,(2,3)) 

輸出:

[[ 1. 9. 5.] 
[ 13. 0. 0.]] 
[[ 4. 12. 8.] 
[ 16. 0. 0.]] 
[[ 0. 0. 0.] 
[ 0. 0. 0.]] 
[[ 0. 0. 0.] 
[ 0. 0. 0.]] 
+2

您的答案似乎開始了「您應該更改Fortran程序以在輸出中使用直接訪問而不是順序訪問」。如果這就是意圖(這是一個重大的變化),也許最好更明確一點呢? – francescalus