Распаковка Python Struct - PullRequest
       6

Распаковка Python Struct

5 голосов
/ 02 марта 2011

У меня есть маленькая проблема, которая беспокоила меня в течение последнего часа или около того.

string = b'-'
t = struct.pack(">h%ds" % len(string), len(string), string)
print(t)

результат этого пакета b '\ x00 \ x01 -'

У меня проблема в том, что я не могу понять, как распаковать результат b '\ x00 \ x01-', чтобы он был просто '-', да. Я знаю, что я могу просто удалить дерьмо в передней части, но это немного сложнее. Я попытался упростить это здесь. Надеюсь, кто-нибудь может мне помочь. :)

Ответы [ 5 ]

5 голосов
/ 02 марта 2011

Обычно вы не используете struct.pack, чтобы соединить заголовок длины и значение.Вместо этого вы просто делаете struct.pack(">h", len(data)), отправляете это по линии (например, в сетевом протоколе) и затем отправляете данные.Не нужно создавать новый байтовый буфер.

В вашем случае вы можете просто сделать:

dataLength, = struct.unpack(">h", t[:2])
data = t[2:2+dataLength]

, но, как я уже сказал, если у вас есть приложение на основе сокетов, например, онобыло бы так:

header = receive(2)
dataLength, = struct.unpack(">h", header)
data = receive(dataLength)
3 голосов
/ 02 марта 2011
import struct
string = b'-'
fmt=">h%ds" % len(string)

Здесь вы упаковываете длину и строку:

t = struct.pack(fmt, len(string), string)
print(repr(t))
# '\x00\x01-'

Таким образом, при распаковке вы должны получить два значения обратно, то есть длину и строку:

length,string2=struct.unpack(fmt,t)
print(repr(string2))
# '-'

В общем, если вы не знаете, как была упакована строка, то нет надежного способа восстановить данные. Вам просто нужно угадать!

Если вы знаете данные состоит из длины строки, а затем сама строка, то вы можно попробовать методом проб и ошибок:

import struct
string = b'-'
fmt=">h%ds" % len(string)
t = struct.pack(fmt, len(string), string)
print(repr(t))

for endian in ('>','<'):
    for fmt,size in (('b',1),('B',1),('h',2),('H',2),('i',4),('I',4),
                     ('l',4),('L',4),('q',8),('Q',8)):
        fmt=endian+fmt
        try:
            length,=struct.unpack(fmt,t[:size])
        except struct.error:
            pass
        else:
            fmt=fmt+'{0}s'.format(length)
            try:
                length,string2=struct.unpack(fmt,t)
            except struct.error:
                pass
            else:
                print(fmt,length,string2)
# ('>h1s', 1, '-')
# ('>H1s', 1, '-')

Возможно, можно составить неоднозначную строку t, которая имеет несколько допустимых распаковок, что приведет к различным string2 с. Я не уверен.

1 голос
/ 02 марта 2011

Давайте просто представим, что data - это большой кусок байтов, и вы успешно проанализировали первые posn байтов. Документация для этого фрагмента байтов гласит, что следующий элемент представляет собой строку байтов, которой предшествует 16-разрядное подписанное (маловероятно, но вы сказали * формат h) бигендовское целое число. Вот что нужно сделать:

nbytes, = struct.unpack('>h', data[posn:posn+2]
posn += 2
the_string = data[posn:posn+nbytes]
posn += nbytes

и теперь вы готовы к следующему предмету.

Примечание. Если вы пишете код, ограниченный Python 2.5 или более поздней версии, вы можете использовать unpack_from()

0 голосов
/ 02 марта 2011

Модуль struct предназначен для блоков данных фиксированного формата. Однако вы можете использовать следующий код:

import struct
t=b'\x00\x01-'
(length,)=struct.unpack_from(">h", t)
(text,)=struct.unpack_from("%ds"%length, t, struct.calcsize(">h"))
print text
0 голосов
/ 02 марта 2011

Как именно вы распаковываете?

>>> string = b'-'
>>> format = '>h%ds' % len(string)
>>> format
'>h1s'
>>> struct.calcsize(format)
3

Для unpack(fmt, string), len(string) должно равняться struct.calcsize(fmt). Таким образом, распакованные данные не могут быть просто '-'.

Но:

>>> t = b'\x00\x01-'
>>> length, data = struct.unpack(format, t)
>>> length, data
(1, '-')

Теперь вы можете использовать data.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...