0

我有一个文件,其中有些行是我可以忽略的元数据,有些行是 struct.pack 调用的打印结果。说 f.txt 是:

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

在这种情况下,以“key”开头的行是元数据,字节字符串是我要提取的值。同样在这种情况下,两个字节字符串行是使用 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:unpack 需要一个长度为 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

如果我将字节字符串直接放入 unpack 调用中,我就成功了:

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

我尝试将以下行的变体传递给解包,所有这些都给出相同的结果:

str(line)
repr(line)
b"%s" % line
4

2 回答 2

3

文本文件中的实际字节是您在 python 控制台上看到的字符串转义字节,而不是它们所代表的二进制字节。

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

您需要先取消转义此文本(将其转换为二进制形式),然后 struct 才能对其进行处理。

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

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

Python 有一个名为的内置编解码器string_escape,它将 python-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)
于 2012-04-19T03:11:22.860 回答
0

对于 txt 文件中的字符串:

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

在python中它实际上是:

\\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
于 2012-04-19T02:51:07.880 回答