Преобразование заполненных нулями байтов в строку UTF-8

Я распаковываю несколько структур, содержащих 's' введите поля из C. Поля содержат заполненные нулями строки UTF-8, обрабатываемые strncpy в коде C (обратите внимание на рудиментарное поведение этой функции). Если я декодирую байты, я получаю строку юникода с большим количеством символов NUL в конце.

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

У меня сложилось впечатление, что конечные нулевые байты являются частью UTF-8 и будут автоматически удалены.

Как правильно удалить нулевые байты?


person Matt Joiner    schedule 22.02.2011    source источник
comment
Готов принять ответ, который может прокомментировать обработку UTF-8 конечных байтов.   -  person Matt Joiner    schedule 22.02.2011
comment
Насколько я понимаю, кодовая точка NULL в Unicode должна быть закодирована в utf-8 как нулевой байт, но поскольку некоторые языки используют null для завершения строки, используется альтернативная кодировка, например. в Java, известный как модифицированный utf-8, который использует C0,80 для кодирования нуля. См. en.wikipedia.org/wiki/UTF-8#Modified_UTF-8   -  person Duncan    schedule 22.02.2011


Ответы (3)


Либо rstrip, либо replace будут работать, только если строка дополняется нулями до конца буфера. На практике буфер, возможно, не был изначально инициализирован нулевым значением, поэтому вы можете получить что-то вроде b'hiya\0x\0'.

Если вы на 100% знаете, что код C начинается с нулевого инициализированного буфера и никогда не использует его повторно, то вы можете найти rstrip более простым, иначе я бы выбрал немного более беспорядочный, но гораздо более безопасный:

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

который обрабатывает первый нуль как терминатор.

person Duncan    schedule 22.02.2011
comment
Вместо этого я бы предложил b'hiya\0x\0'.partition(b'\0')[0]. - person tzot; 16.03.2011
comment
Хороший звонок. Я всегда забываю о partition. - person Duncan; 16.03.2011

Используйте str.rstrip(), чтобы удалить конечные значения NUL:

>>> 'hiya\0\0\0'.rstrip('\0')
'hiya'
person Adam Rosenfield    schedule 22.02.2011
comment
Это может привести к ошибке, если c-строка не была инициализирована нулями или старая строка была перезаписана более короткой. Когда переменная c-string изменяется, только байт после последнего символа устанавливается равным нулю. - person phobie; 20.01.2013
comment
Это не доказывает, что вывод не имеет завершающих нулей, потому что если они есть, он не будет напечатан. Однако, если вы используете len(), это, вероятно, поможет, так как len не заботится о конечных нулях. - person Nawaz; 16.09.2015

В отличие от решения split/partition, это не копирует несколько строк и может быть быстрее для длинных байтовых массивов.

data = b'hiya\0\0\0'
i = data.find(b'\x00')
if i == -1:
  return data
return data[:i]
person phobie    schedule 19.01.2013
comment
то же, что data[:data.find(0)] - person iperov; 01.03.2021
comment
Нет, этот код не будет работать, если буфер заполнен (не содержит нулей). т.е. data = b'hiyafoo' - person phobie; 02.03.2021