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

この場合、「キー」で始まる行はメタデータであり、バイト文字列は抽出したい値です。この場合も、2 バイトの文字列行が 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')

次のバリエーションの行を unpack に渡そうとしましたが、すべて同じ結果が得られます。

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

2 に答える 2

3

テキストファイルの実際のバイトは、Pythonコンソールに表示される文字列エスケープされたバイトであり、それらが表すバイナリバイトではありません。

たとえば、テキストファイルには\x00ヌルバイト(1バイト長)ではなく(4バイト長)が含まれています。

structが機能する前に、このテキストをエスケープ解除する(バイナリ形式に変換する)必要があります。

(数値であるが「key:」で始まる行がある可能性があるため、ファイル形式はあまり良くないことに注意してください!たとえば'key: \x00\x00\x00'、有効な数値6.8388560679e-313です!メタデータと値を1行おきに切り替える場合は、そのままにしておく必要があります。現在の行番号を追跡し、それに応じて解析します。)

ここには他のものよりもはるかに簡単な解決策があります。

string_escapePythonには、 pythonエスケープコードをそれらが表すバイナリバイトに変換するというコーデックが組み込まれています。

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

これらのdouble値の大きなリストがあり、それらを配列構造に効率的に格納したい場合は、次の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 に答える