2012-04-19 114 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) 
相關問題