2012-04-19 118 views
0

我有一个文件,其中一些行是元数据,我可以忽略,一些行是struct.pack调用的打印结果。再说说f.txt是:当我的字符串长度正确时,为什么struct.unpack()会引发异常?

key: 3175 
\x00\x00\x00\x00\x00\x00\x00\x00 
key: 3266 
\x00\x00\x00\x00\x00\x00\x00\x00 

在这种情况下,该行开始的“钥匙”是元数据和字节字符串我想提取的值。同样在这种情况下,两个字节的字符串行用struct.pack('d',0)生成。下面的代码是我想怎样做:

import struct 
for line in open('f.txt', 'r'):  
    # if not metadata, remove newline character and unpack 
    if line[0:3] != 'key': 
    val = struct.unpack('d', line[0:-1]) 
    appendToList(val) # do something else with val 

有了这个,我得到:“struct.error:解压需要长度为8的字符串参数”。

如果我们修改略有代码:

import struct 
for line in open('f.txt', 'r'):  
    # if not metadata, remove newline character and unpack 
    if line[0:3] != 'key': print line[:-1] 

则如预期输出:

\x00\x00\x00\x00\x00\x00\x00\x00 
\x00\x00\x00\x00\x00\x00\x00\x00 

如果我把字节串直接进入解压电话以后,我就成功:

import struct 
# successful unpacking 
struct.unpack('d', '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') 

我已经尝试传递以下变化的行来解压,所有这些都给出了相同的r esult:

str(line) 
repr(line) 
b"%s" % line 
+2

确实错误没有在文件的最后一行发生,这可能是缺少一个换行符? – vanza 2012-04-19 02:18:02

+0

解包的第一个电话不成功,所以情况并非如此。 – arbenson 2012-04-19 02:37:47

回答

0

您在TXT文件字符串:

\x00\x00\x00\x00\x00\x00\x00\x00 

这蟒蛇它acturally是:

\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00 

所以你应该分析这个字符串,并将其转换。为您的样品,使用下面的代码可以得到你想要的东西:

s = line.strip().split('\\x') 
r = '' 
for v in s: 
    if len(v) > 0: 
     print v 
     r += struct.pack('b', int(v, 16)) 
val = struct.unpack('d', r)[0] 
print val 
+0

这工作。谢谢唐纳德。 – arbenson 2012-04-19 02:54:48

+1

不要添加字符串'''.join'它们。字符串是不可变的,所以重复添加它们非常缓慢。 – agf 2012-04-19 02:55:41

+0

@arbenson,既然你显然不关心性能,为什么不把浮点数的'repr()'写到文件中,然后用'float() – 2012-04-19 03:07:05

3

在文本文件中的实际字节字符串转义字节你在一个Python控制台中看到的,不是他们所代表的二进制字节。

例如,您的文本文件包含\x00(四个字节长),而不是空字节(一个字节长)。

在struct可以使用它之前,您需要将此文本转换为二进制形式。

(请注意,您的文件格式也不是很好,因为你可以想象有一条线,是一个数字,但开头“键:”如'key: \x00\x00\x00'是有效数字6.8388560679e-313如果您的元数据和值每间交替!其他行,你应该保持跟踪你所在的行号,并相应地进行解析。)

这里有一个比其他人更简单的解决方案。

Python有一个内置的解码器称为string_escape将蟒蛇逃逸代码转换成二进制字节它们代表:

for line in thefile: 
    if line[0:3] != 'key': 
     binaryline = line[:-1].decode('string_escape') 
     val = struct.unpack('d', binaryline) 

如果您有这些双值的大名单,并希望它们有效地存储在一个阵列结构,可以考虑使用array模块,而不是struct

vals = array.array('d') 

for line in thefile: 
    if line[0:3] != 'key': 
     binaryline = line[:-1].decode('string_escape') 
     # appends binaryline to vals array, interpreting as a double 
     vals.fromstring(binaryline) 
相关问题