Как читать байты в кодировке UTF16-BE с заголовком длины - PullRequest
0 голосов
/ 23 января 2020

Я хочу декодировать ряд строк переменной длины, которые были закодированы в UTF16-BE, перед которым стоит двухбайтовое целое число с прямым порядком байтов, указывающее половину длины байта следующей строки. Например:

Length    String (encoded)           Length    String (encoded)               ...
\x00\x05  \x00H\x00e\x00l\x00l\x00o  \x00\x06  \x00W\x00o\x00r\x00l\x00d\x00! ...

Все эти строки и их заголовки длины объединены в один большой bytestring.

У меня закодированная строка байтов как объект bytes в памяти. Я хотел бы иметь итеративную функцию, которая выдала бы строки, пока не достигнет конца ByteString.

Ответы [ 2 ]

1 голос
/ 23 января 2020

Не большое улучшение, но ваш код может быть немного упрощен.

def decode_strings(byte_string: ByteString) -> Generator[str]:
    with io.BytesIO(byte_string) as stream:
        while (s := stream.read(2)):
            length = int.from_bytes(s, byteorder="big")
            yield bytes.decode(stream.read(length), encoding="utf_16_be")
0 голосов
/ 23 января 2020

В настоящее время я делаю это так, но каким-то образом я воображаю Раймона Хеттингера «Должен быть лучший способ!» .

import io
import functools
from typing import ByteString
from typing import Iterable

# Decoders
int_BE = functools.partial(int.from_bytes, byteorder="big")
utf16_BE = functools.partial(bytes.decode, encoding="utf_16_be")

encoded_strings = b"\x00\x05\x00H\x00e\x00l\x00l\x00o\x00\x06\x00W\x00o\x00r\x00l\x00d\x00!"
header_length = 2

def decode_strings(byte_string: ByteString) -> Iterable[str]:
    stream = io.BytesIO(byte_string)
    while True:
        length = int_BE(stream.read(header_length))
        if length:
            text = utf16_BE(stream.read(length * 2))
            yield text
        else:
            break
    stream.close()


if __name__ == "__main__":
    for text in decode_strings(encoded_strings):
        print(text)

Спасибо за любые предложения.

...