如何读取长度为 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")
我想解码一系列可变长度的字符串,这些字符串以 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")