如何读取带有长度标头的UTF16BE编码字节

2024-06-17 09:03:50 发布

您现在位置:Python中文网/ 问答频道 /正文

我想解码一系列用UTF16编码的可变长度字符串,前面是一个两字节长的big-endian整数,表示以下字符串字节长度的一半。e、 g:

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

所有这些字符串及其长度头都连接在一个大的bytestring

我在内存中将编码的bytestring作为bytes对象。我想要一个iterable函数,它将产生字符串,直到它到达ByteString的末尾


Tags: 字符串编码string字节整数解码lengthencoded
2条回答

目前我是这样做的,但不知怎么的,我在想象雷蒙德·海廷格的"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")

相关问题 更多 >