在Python中读取直接访问二进制文件格式

Mar*_* P. 6 python fortran binaryfiles

背景:

使用以下Fortran代码在Linux机器上读取二进制文件:

        parameter(nx=720, ny=360, nday=365)
c 
        dimension tmax(nx,ny,nday),nmax(nx,ny,nday)
        dimension tmin(nx,ny,nday),nmin(nx,ny,nday)
c 
        open(10,
     &file='FILE',
     &access='direct',recl=nx*ny*4)
c
        do k=1,nday
        read(10,rec=(k-1)*4+1)((tmax(i,j,k),i=1,nx),j=1,ny) 
        read(10,rec=(k-1)*4+2)((nmax(i,j,k),i=1,nx),j=1,ny) 
        read(10,rec=(k-1)*4+3)((tmin(i,j,k),i=1,nx),j=1,ny) 
        read(10,rec=(k-1)*4+4)((nmin(i,j,k),i=1,nx),j=1,ny) 
        end do
Run Code Online (Sandbox Code Playgroud)

档案细节:

options  little_endian
title global daily analysis (grid box mean, the grid shown is the center of the grid box)
undef -999.0
xdef 720 linear    0.25 0.50
ydef 360  linear -89.75 0.50
zdef 1 linear 1 1
tdef 365 linear 01jan2015 1dy
vars 4
tmax     1  00 daily maximum temperature (C)
nmax     1  00 number of reports for maximum temperature (C)
tmin     1  00 daily minimum temperature (C)
nmin     1  00 number of reports for minimum temperature (C)
ENDVARS
Run Code Online (Sandbox Code Playgroud)

尝试解决方案:

我试图使用以下代码将此解析为python中的数组(故意遗漏两个属性):

with gzip.open("/FILE.gz", "rb") as infile:
     data = numpy.frombuffer(infile.read(), dtype=numpy.dtype('<f4'), count = -1)

while x <= len(data) / 4:
    tmax.append(data[(x-1)*4])
    tmin.append(data[(x-1)*4 + 2])
    x += 1

data_full = zip(tmax, tmin)
Run Code Online (Sandbox Code Playgroud)

在测试某些记录时,使用Fortran时,数据似乎与文件中的某些样本记录不一致.我也尝试过dtype=numpy.float32没有成功.好像我正在以观察数量的方式正确阅读文件.struct在我了解文件是用Fortran创建之前我也在使用.那不行

这里也有类似的问题,其中一些问题我已经尝试过适应没有运气的答案.

UPDATE

尝试这段代码后,我离我更近了一点:

#Define numpy variables and empty arrays
nx = 720 #number of lon
ny = 360 #number of lat
nday = 0 #iterate up to 364 (or 365 for leap year)   
tmax = numpy.empty([0], dtype='<f', order='F')
tmin = numpy.empty([0], dtype='<f', order='F')

#Parse the data into numpy arrays, shifting records as the date increments
while nday < 365:
    tmax = numpy.append(tmax, data[(nx*ny)*nday:(nx*ny)*(nday + 1)].reshape((nx,ny), order='F'))
    tmin = numpy.append(tmin, data[(nx*ny)*(nday + 2):(nx*ny)*(nday + 3)].reshape((nx,ny), order='F'))
    nday += 1  
Run Code Online (Sandbox Code Playgroud)

我得到第一天的正确数据,但是第二天我得到全零,第三天最大值低于最小值,依此类推.

Mar*_* P. 1

在我的问题更新后,我意识到我的循环方式出现了错误。当然,我在发出赏金后大约 10 分钟就发现了这一点,哦,好吧。

错误在于使用日期来迭代记录。这将不起作用,因为它每个循环迭代一次,没有将记录推得足够远。这就是为什么有些分钟值高于最大值的原因。新代码是:

while nday < 365:
    tmax = numpy.append(tmax, data[(nx*ny)*rm:(nx*ny)*(rm + 1)].reshape((nx,ny), order='F'))
    rm = rm + 2
    tmin = numpy.append(tmin, data[(nx*ny)*rm:(nx*ny)*(rm + 1)].reshape((nx,ny), order='F'))
    rm = rm + 2
    nday += 1 
Run Code Online (Sandbox Code Playgroud)

这使用记录移动器(或rm我所说的)将记录移动适当的数量。这就是它所需要的一切。