Как определить длину байта строки в кодировке utf-8 в Python? - PullRequest
23 голосов
/ 16 июля 2011

Я работаю с загрузками Amazon S3, и у меня возникают проблемы с слишком длинными именами ключей. S3 ограничивает длину ключа байтами, а не символами.

Из документов:

Имя ключа - это последовательность символов Unicode, длина кодировки UTF-8 которых не превышает 1024 байта.

Я также пытаюсь внедрить метаданные в имя файла, поэтому мне нужно иметь возможность рассчитать текущую длину строки в байтах с помощью Python, чтобы убедиться, что метаданные не делают ключ слишком длинным (в этом случае я бы использовать отдельный файл метаданных).

Как определить длину в байтах кодированной строки utf-8? Опять же, меня не интересует длина символа ... скорее фактическая длина байта, используемая для хранения строки.

Ответы [ 3 ]

36 голосов
/ 16 июля 2011
def utf8len(s):
    return len(s.encode('utf-8'))

Отлично работает в Python 2 и 3.

8 голосов
/ 16 июля 2011

Используйте метод string 'encode' для преобразования строки символов в строку байтов, затем используйте len () как обычно:

>>> s = u"¡Hola, mundo!"                                                      
>>> len(s)                                                                    
13 # characters                                                                             
>>> len(s.encode('utf-8'))   
14 # bytes
4 голосов
/ 23 сентября 2013

Кодирование строки и использование len в результате отлично работает, как показали другие ответы. Нужно создать одноразовую копию строки - если вы работаете с очень большими строками, это может быть неоптимально (хотя я не считаю 1024 байта большими ). Структура UTF-8 позволяет очень легко получить длину каждого символа, даже не кодируя его, хотя все еще может быть проще кодировать один символ. Я представляю оба метода здесь, они должны давать одинаковый результат.

def utf8_char_len_1(c):
    codepoint = ord(c)
    if codepoint <= 0x7f:
        return 1
    if codepoint <= 0x7ff:
        return 2
    if codepoint <= 0xffff:
        return 3
    if codepoint <= 0x10ffff:
        return 4
    raise ValueError('Invalid Unicode character: ' + hex(codepoint))

def utf8_char_len_2(c):
    return len(c.encode('utf-8'))

utf8_char_len = utf8_char_len_1

def utf8len(s):
    return sum(utf8_char_len(c) for c in s)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...