Python长度的unicode字符串混淆

Posted

技术标签:

【中文标题】Python长度的unicode字符串混淆【英文标题】:Python length of unicode string confusion 【发布时间】:2015-06-11 08:37:45 【问题描述】:

已经有很多帮助,但我仍然很困惑。

我有一个这样的 unicode 字符串:

title = u'????test'
title_length = len(title) #5

但是!我需要 len(title) 为 6。客户希望它为 6,因为他们的计数方式似乎与我在后端的计算方式不同。

作为一种解决方法,我编写了这个小助手,但我确信它可以改进(对编码有足够的了解),或者它甚至可能是错误的。

title_length = len(title) + repr(title).count('\\U') #6

1.有没有更好的方法让长度为 6? :-)

我假设我(Python)正在计算 unicode 字符的数量,即 5。客户端正在计算字节数?

2。对于其他需要 4 个字节的 unicode 字符,我的逻辑会中断吗?

运行 Python 2.7 ucs4。

【问题讨论】:

客户端统计 UTF-16 代理对。 当我尝试运行这两行时,它显示的长度为 6。 @ssundarraj:看我的回答;您正在运行 Python 2 UCS2 构建。使用 Python 3.3 或更高版本,或者自己构建 UCS4。 【参考方案1】:

您有 5 个代码点。其中一个代码点位于 Basic Multilingual Plane 之外,这意味着这些代码点 has to use two code units for the character 的 UTF-16 编码。

换句话说,客户端依赖于一个实现细节,并且做错了什么。他们应该计算代码,而不是代码单位。有几个平台经常发生这种情况; Python 2 UCS2 构建就是其中之一,但 Java 开发人员经常忘记区别,Windows API 也是如此。

您可以将文本编码为 UTF-16 并将字节数除以 2(每个 UTF-16 代码单元为 2 个字节)。选择 utf-16-leutf-16-be 变体以在长度中不包含 BOM:

title = u'?test'
len_in_codeunits = len(title.encode('utf-16-le')) // 2

如果您使用的是 Python 2(并根据您可能使用的字符串的 u 前缀判断),请考虑到 Python 有两种不同的风格,具体取决于您构建它的方式。根据构建时配置开关,您将拥有 UCS-2 或 UCS-4 构建;前者在 internally 中也使用了代理项,并且您的 title 值长度也将是 6。见Python returns length of 2 for single Unicode character string。

【讨论】:

客户端确实是 Java,你怎么知道他们在计算 UTF-16 代理对?难道它也不能是 UTF-8 或 UTF-32 吗?我可以确定他们总是计算 2 个代码单元,取决于代码点可能更多吗?你的计数方法看起来确实更优雅。 :-) 非常感谢您的精彩解释! 如果他们在不同的 UTF 编解码器中计算代码单元(UTF-8 中为 8,UTF-32 中为 5),则计数会大不相同。是的,UTF-16 总是使用一个或两个代码单元,请参阅我的答案中的 Wikipedia 链接。 Java代码可以固定;见JSR-204 和codePointCount() method。

以上是关于Python长度的unicode字符串混淆的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server中易混淆的数据类型

Python 为单个 Unicode 字符串返回长度为 2

如何从python中的unicode字符串中删除除数字和“,”之外的所有字符?

Unicode(UTF-8, UTF-16)令人混淆的概念

Unicode(UTF-8, UTF-16)令人混淆的概念

Unicode(UTF-8, UTF-16)令人混淆的概念