我编写了一个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()
效果很好,然后我尝试使用下面的代码阅读'test.bin'文件。
import struct
inh = open('test.bin', 'rb')
for rec in inh:
pos = struct.unpack('i', rec)
print pos
inh.close()
但它失败并显示错误消息:
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
我想知道如何使用struct.unpack
阅读这些文件
提前谢谢了,
VIPIN
答案 0 :(得分: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)
如果您确实害怕潜在的大量数据(这会占用比您可用的更多的内存),一个简单的生成器提供了一个优雅的选择:
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)
第二种方法的一个关键优势是可以轻松调整by4
生成器(同时保持规范:一次返回二进制文件的4个字节数据)以使用不同的实现策略进行缓冲,所有通往第一种方法的方式(读取所有内容然后将其包裹起来),这可以被视为“无限缓冲”并编码:
def by4(f):
data = inf.read()
for i in range(0, len(data), 4):
yield data[i:i+4]
同时保留“应用程序逻辑”(做什么与4字节块的流)完整且独立于I / O层(它被封装在生成器中)。
答案 1 :(得分:5)
我认为“for in in inh”应该是'lines'而不是字节。你想要的是:
while True:
rec = inh.read(4) # Or inh.read(struct.calcsize('i'))
if len(rec) != 4:
break
(pos,) = struct.unpack('i', rec)
print pos
或正如其他人所说:
while True:
try:
(pos,) = struct.unpack_from('i', inh)
except (some_exception...):
break
答案 2 :(得分:1)
检查打包整数的大小:
>>> pos
[7623, 3015, 3231, 3829]
>>> [struct.pack('i',e) for e in pos]
['\xc7\x1d\x00\x00', '\xc7\x0b\x00\x00', '\x9f\x0c\x00\x00', '\xf5\x0e\x00\x00']
我们看到4字节字符串,这意味着一次读取应该是4个字节:
>>> inh=open('test.bin','rb')
>>> b1=inh.read(4)
>>> b1
'\xc7\x1d\x00\x00'
>>> struct.unpack('i',b1)
(7623,)
>>>
这是原来的int!延伸到阅读循环是一个练习。
答案 3 :(得分:1)
如果您愿意,也可以使用array
:
import array
pos = array.array('i', [7623, 3015, 3231, 3829])
inh = open('test.bin', 'wb')
pos.write(inh)
inh.close()
然后使用array.array.fromfile
或fromstring
将其读回。
答案 4 :(得分:1)
此函数读取文件
中的所有字节def read_binary_file(filename):
try:
f = open(filename, 'rb')
n = os.path.getsize(filename)
data = array.array('B')
data.read(f, n)
f.close()
fsize = data.__len__()
return (fsize, data)
except IOError:
return (-1, [])
# somewhere in your code
t = read_binary_file(FILENAME)
fsize = t[0]
if (fsize > 0):
data = t[1]
# work with data
else:
print 'Error reading file'
答案 5 :(得分:0)
你的迭代器一次不读4个字节,所以我觉得它很混乱。就像SilentGhost提到的那样,最好使用unpack_from()。