将零填充字节转换为UTF-8字符串

24 投票
3 回答
29413 浏览
提问于 2025-04-16 12:16

我正在解包几个包含C语言中's'类型字段的结构体。这些字段里有用零填充的UTF-8字符串,这些字符串在C代码中是通过strncpy这个函数处理的(注意这个函数的一些古怪行为)。如果我直接解码这些字节,就会得到一个包含很多NUL字符的Unicode字符串。

>>> b'hiya\0\0\0'.decode('utf8')
'hiya\x00\x00\x00'

我原以为末尾的零字节是UTF-8的一部分,会自动被去掉。

那么,去掉这些零字节的正确方法是什么呢?

3 个回答

3

跟分割或划分的方法不同,这种方法不会复制多个字符串,对于很长的字节数组来说,可能会更快。

data = b'hiya\0\0\0'
i = data.find(b'\x00')
if i == -1:
  return data
return data[:i]
25

使用 str.rstrip() 方法可以去掉字符串末尾的空字符(NULs):

>>> 'hiya\0\0\0'.rstrip('\0')
'hiya'
26

无论是 rstrip 还是 replace,只有在字符串的末尾用空字符填充的情况下才能正常工作。实际上,缓冲区可能一开始就没有被初始化为空字符,所以你可能会看到像 b'hiya\0x\0' 这样的情况。

如果你百分之百确定 C 代码是从一个已经初始化为空字符的缓冲区开始,并且绝对不会重复使用它,那么你可能会觉得 rstrip 更简单。不过,如果不确定的话,我建议使用稍微复杂一点但更安全的方法:

>>> b'hiya\0x\0'.split(b'\0',1)[0]
b'hiya'

这种方法把第一个空字符当作结束符。

撰写回答