如何读取长度为 header 的 UTF16-BE 编码字节

How to read UTF16-BE encoded bytes with length header

我想解码一系列可变长度的字符串,这些字符串以 UTF16-BE 编码,前面有一个 two-bytes 长 big-endian 整数,表示 byte-length 的一半以下字符串。例如:

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

所有这些字符串及其长度 headers 连接成一个大 bytestring

我在内存中有 bytes object 编码的字节串。我想要一个可迭代函数,它会产生字符串,直到它到达 ByteString 的末尾。

目前我是这样做的,但不知何故我正在想象 Raymond Hettinger 的 "There must be a better way!"

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)

感谢您的任何建议。

改进不大,但您的代码可以稍微精简一下。

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")