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

背景:


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


        parameter(nx=720, ny=360, nday=365)

        dimension tmax(nx,ny,nday),nmax(nx,ny,nday)

        dimension tmin(nx,ny,nday),nmin(nx,ny,nday)

        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

文件详情:


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

尝试解决方案:


我正在尝试使用以下代码(故意省略两个属性)将其解析为 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)

在测试某些记录时,使用 Fortran 时,数据似乎与文件中的某些示例记录不一致。我也尝试dtype=numpy.float32过,但没有成功。就观察次数而言,似乎我正在正确读取文件。struct在我知道文件是用 Fortran 创建的之前,我也在使用。那不起作用


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


阿波罗的战车
浏览 212回答 2
2回答

紫衣仙女

在我的问题中更新之后,我意识到我的循环方式有误。我当然在发出赏金后大约 10 分钟发现了这一点,好吧。错误在于使用一天来遍历记录。这将不起作用,因为它每个循环迭代一次,没有将记录推得足够远。因此,为什么有些分钟高于最大值。新代码是:while nday < 365:&nbsp; &nbsp; tmax = numpy.append(tmax, data[(nx*ny)*rm:(nx*ny)*(rm + 1)].reshape((nx,ny), order='F'))&nbsp; &nbsp; rm = rm + 2&nbsp; &nbsp; tmin = numpy.append(tmin, data[(nx*ny)*rm:(nx*ny)*(rm + 1)].reshape((nx,ny), order='F'))&nbsp; &nbsp; rm = rm + 2&nbsp; &nbsp; nday += 1&nbsp;这使用了记录移动器(或rm我称之为)来移动记录适当的数量。这就是它所需要的。

鸿蒙传说

虽然 Fortran 二进制文件的确切格式取决于编译器,但在所有情况下,我都知道直接访问文件(access='direct'如本问题中那样打开的文件)在记录之间没有任何记录标记。每条记录的大小都是固定的,由语句recl=中的OPEN说明符给出。也就是说,记录N从(N - 1) * RECL文件中的偏移字节开始。一个可移植性问题是 的单位recl=是file storage units。对于大多数编译器,file storage unit以 8 位八位字节指定大小(如 Fortran 标准的最新版本所推荐),但对于英特尔 Fortran 编译器,recl=以 32 位为单位;有一个命令行选项-assume byterecl可用于使英特尔 Fortran 与大多数其他编译器相匹配。因此,在此处给出的示例中,假设为 8 位file storage unit,则您的 recl 将为 1036800 字节。此外,查看代码,似乎假设数组是 4 字节类型(例如整数或单精度实数)。因此,如果它是单精度实数,并且文件是以小端创建的,那么<f4您使用的 numpy dtype似乎是正确的选择。现在,回到英特尔 Fortran 编译器的问题上,如果文件是由 ifort 创建的,-assume byterecl那么您想要的数据将位于每条记录的第一季度,其余部分是填充(全为零或什至随机数据?) .&nbsp;然后你必须做一些额外的体操来提取python中的正确数据而不是填充。通过检查文件的大小,是它nx * ny * 4 * nday *4还是nx * ny * 4 * nday * 4 * 4字节,应该很容易检查这一点?
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python