在python中读取二进制文件

Vip*_*pin 2 python

我写了一个python脚本来创建一个整数的二进制文件.

import struct  
pos = [7623, 3015, 3231, 3829]  
inh = open('test.bin', 'wb')  
for e in pos:  
    inh.write(struct.pack('i', e))  
inh.close()
Run Code Online (Sandbox Code Playgroud)

它工作得很好,然后我尝试使用下面的代码读取'test.bin'文件.

import struct  
inh = open('test.bin', 'rb')  
for rec in inh:  
    pos = struct.unpack('i', rec)  
    print pos  
inh.close()
Run Code Online (Sandbox Code Playgroud)

但它失败并显示错误消息:

Traceback (most recent call last):   
   File "readbinary.py", line 10, in <module>  
   pos = struct.unpack('i', rec)  
   File "/usr/lib/python2.5/struct.py", line 87, in unpack  
   return o.unpack(s)  
struct.error: unpack requires a string argument of length 4
Run Code Online (Sandbox Code Playgroud)

我想知道如何使用这些文件阅读struct.unpack.
非常感谢,Vipin

Ale*_*lli 8

for rec in inh:一次读取一行 - 不是您想要的二进制文件.改为一次读取4个字节(使用while循环和inh.read(4))(或者通过一次.read()调用将所有内容读入内存,然后解压缩连续的4字节切片).第二种方法最简单,最实用,只要涉及的数据量不大:

import struct
with open('test.bin', 'rb') as inh:
    indata = inh.read()
for i in range(0, len(data), 4):
    pos = struct.unpack('i', data[i:i+4])  
    print(pos)  
Run Code Online (Sandbox Code Playgroud)

如果您确实害怕潜在的大量数据(这将占用比您可用的更多的内存),一个简单的生成器提供了一个优雅的替代方案:

import struct
def by4(f):
    rec = 'x'  # placeholder for the `while`
    while rec:
        rec = f.read(4)
        if rec: yield rec           
with open('test.bin', 'rb') as inh:
    for rec in by4(inh):
        pos = struct.unpack('i', rec)  
        print(pos)  
Run Code Online (Sandbox Code Playgroud)

第二种方法的一个关键优势是by4可以轻松调整生成器(同时保持规范:一次返回二进制文件的4个字节数据),以使用不同的实现策略进行缓冲,一直到第一种方法(读取)然后把所有东西包裹起来)可以看作"无限缓冲"并编码:

def by4(f):
    data = inf.read()
    for i in range(0, len(data), 4):
        yield data[i:i+4]
Run Code Online (Sandbox Code Playgroud)

同时留下了"应用逻辑"(什么具有4个字节的组块流)完整和独立的I/O层(其被所述发电机内封装的).

  • 一旦"rec = f.read(4)"返回零,by4的第一个版本将挂起.while循环没有退出. (2认同)

ond*_*dra 5

我认为“ for rec in inh”应该读取“行”,而不是字节。您想要的是:

while True:
    rec = inh.read(4) # Or inh.read(struct.calcsize('i'))
    if len(rec) != 4:
        break
    (pos,) = struct.unpack('i', rec)
    print pos
Run Code Online (Sandbox Code Playgroud)

或者像其他人提到的那样:

while True:
    try:
        (pos,) = struct.unpack_from('i', inh)
    except (some_exception...):
        break
Run Code Online (Sandbox Code Playgroud)