我正在处理Amazon S3上传,并且遇到了键名过长的问题。S3限制键名长度以字节为单位,而非字符。
来自文档的说明:
键名是一个Unicode字符序列,其UTF-8编码最多为1024个字节。
我还尝试在文件名中嵌入元数据,因此需要能够使用Python计算字符串的当前字节长度,以确保元数据不会使键名过长(在这种情况下,我将不得不使用单独的元数据文件)。
如何确定utf-8编码字符串的字节长度?再次强调,我不关心字符长度…而是用于存储字符串的实际字节长度。
def utf8len(s):
return len(s.encode('utf-8'))
在Python 2和3中都运行良好。
>>> s = u"¡Hola, mundo!"
>>> len(s)
13 # characters
>>> len(s.encode('utf-8'))
14 # bytes
str
作为变量名!这将导致许多问题。 - Mark Ransom把字符串进行编码并在结果上使用 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)
len(s.encode('utf-8'))
多180倍,至少在我的Python 3.3.2上,对于一个包含1000个UTF8字符的字符串从这里生成。(如果你用C语言编写相同的算法,速度应该是相当的。) - Danicautf8_char_len_2
版本的速度比utf8_char_len_1
慢大约1.5倍。当然,我们在每种情况下都只谈论不到一毫秒的时间,所以如果你只是偶尔这样做,那就无关紧要:2微秒/375微秒/600微秒。话虽如此,复制1kb的内存也不太可能有影响。 :) - Danica