使用np.fromfile或open&读取fortran二进制文件(流媒体访问)结构

时间:2016-09-09 10:59:25

标签: python io binary hex

以下Fortran代码:

INTEGER*2 :: i, Array_A(32)
Array_A(:) = (/ (i, i=0, 31) /)

OPEN (unit=11, file = 'binary2.dat', form='unformatted', access='stream')
    Do i=1,32
        WRITE(11) Array_A(i)
    End Do 
CLOSE (11)

生成流式二进制输出,数字从0到31,整数为16位。每条记录占用2个字节,因此它们写在字节1,3,5,7等等。 access ='stream'为每条记录抑制了Fortran的标准头(我需要这样做才能使文件保持尽可能小)。

使用Hex-Editor查看它,我得到:

00 00 01 00 02 00 03 00 04 00 05 00 06 00 07 00 
08 00 09 00 0A 00 0B 00 0C 00 0D 00 0E 00 0F 00
10 00 11 00 12 00 13 00 14 00 15 00 16 00 17 00
18 00 19 00 1A 00 1B 00 1C 00 1D 00 1E 00 1F 00

这是完全正常的(尽管从未使用过第二个字节,因为在我的例子中小数太低了。)

现在我需要将这些二进制文件导入Python 2.7,但我不能。我尝试了很多不同的例程,但我总是这样做。

1。尝试:“np.fromfile”

with open("binary2.dat", 'r') as f:
    content = np.fromfile(f, dtype=np.int16)

返回

[    0     1     2     3     4     5     6     7     8     9    10    11
    12    13    14    15    16    17    18    19    20    21    22    23
    24    25     0     0 26104  1242     0     0]

2。尝试:“struct”

import struct
with open("binary2.dat", 'r') as f:
    content = f.readlines()
    struct.unpack('h' * 32, content)

发送

struct.error: unpack requires a string argument of length 64

,因为

print content
['\x00\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08\x00\t\x00\n', '\x00\x0b\x00\x0c\x00\r\x00\x0e\x00\x0f\x00\x10\x00\x11\x00\x12\x00\x13\x00\x14\x00\x15\x00\x16\x00\x17\x00\x18\x00\x19\x00']

(注意根据Fortran的“流媒体”访问权限,分隔符,t和n不应该存在)

第3。尝试:“FortranFile”

f = FortranFile("D:/Fortran/Sandbox/binary2.dat", 'r')
print(f.read_ints(dtype=np.int16))

错误:

TypeError: only length-1 arrays can be converted to Python scalars

(记住它是如何在文件中间检测到分隔符的,但是对于没有换行符的较短文件(例如从0到8的小数)也会崩溃)

其他一些想法:

Python似乎在阅读部分二进制文件时遇到麻烦。对于np.fromfile,它会显示Hex 19(十进制:25),但会因Hex 1A(十二月二十六日)而崩溃。它似乎与字母相混淆,虽然0A,0B ......工作得很好。

对于尝试2,content - 结果很奇怪。小数0到8工作正常,但是有一个奇怪的\t\x00\n。那么hex 09是什么?

我花了好几个小时试图找到逻辑,但我被困住了,真的需要一些帮助。有什么想法吗?

1 个答案:

答案 0 :(得分:3)

问题出在打开文件模式。默认为'text'。将此模式更改为二进制:

with open("binary2.dat", 'rb') as f:
    content = np.fromfile(f, dtype=np.int16)

并且所有数字都将成功呈现。有关详细信息,请参阅Dive in Python章节Binary Files