读取16字节的Fortran会从文件浮入Python

时间:2018-09-29 11:44:29

标签: python fortran binaryfiles binary-data

我正在将来自Fortran的浮点序列写入二进制文件,并希望以Python读取它们。使用单精度和双精度浮点数(kind = 4)和(kind = 8)都可以正常工作,但是当我尝试移动到实数(kind = 16)变量类型时,突然事情不再起作用了(数据数组填充了零) 。我在这里读到: python read 16 bytes long double from binary file np.fromfile函数需要一种解决方法。我实施了建议的更改,但仍未得到正确的结果。 Mwe Python和Fortran代码在下面。我用Python 2.7 + Numpy 1.8和Python 3.4 + Numpy 1.14尝试了相同的效果。我还检查了一下,生成的文件似乎具有正确的数据量(480字节,包含16个字节的30个浮点)。任何帮助都将受到欢迎!

Python阅读器:

UI

Fortran编写器(在Ubuntu 14.04上与gfortran 4.8.6编译)

import numpy as np

inputfilename = "fortranData.bin"

dp = 8
nVals = 30

with open(inputfilename, 'rb') as f:
    # both work fine for 4 or 8 byte floats (32 and 64)
    # but not for 16 byte floats (np.float128)
    data = np.fromfile(f, dtype=np.float64)
    data = np.frombuffer(f.read(dp*nVals), dtype=np.float64, count=nVals)

print(data)

编辑:根据要求,以下是fortranData.bin文件顶部的几行数据:

program test

implicit none

integer, parameter :: dp=8
integer, parameter :: outFileUnit=51, nPts=10, nDim=3
character(len=100) :: binaryFile="fortranData.bin"
real(kind=dp), dimension(nPts,nDim) :: data
integer :: i, j

! - generate data -
do i=1, nPts
    do j=1, nDim
        data(i,j) = (i-1)*nDim + j
    enddo
enddo

! - open file and write data -
open(unit=outFileUnit, file=binaryFile, form='unformatted', access='direct', &
    status='replace', recl=nDim*sizeof(data(1,1)))

do i=1, nPts
    write(outFileUnit, rec=i) data(i,:)
enddo

end program test

1 个答案:

答案 0 :(得分:1)

据我所知,numpy不支持IEEE Quad格式,据我所知它只需要手动转换。例如,如果您以16个字节的块为单位读取文件,则可以像这样转换块(尽管测试不佳)

def rawQuadToDouble(raw):
    asint = int.from_bytes(raw, byteorder='little')
    sign = (-1.0) ** (asint >> 127);
    exponent = ((asint >> 112) & 0x7FFF) - 16383;
    significand = (asint & ((1 << 112) - 1)) | (1 << 112)
    return sign * significand * 2.0 ** (exponent - 112)