关于具有特殊字符的len str

时间:2018-01-08 13:58:55

标签: python unicode

像Python中的一些特殊角色,如果它是一个角色。

>>> s = ''
>>> len(s)
3
>>> s[:1]
''

但是当我把它放在Atom中时,它就是2个字符 enter image description here

另外在java中它也是2个字符

jshell> String s = ""
s ==> ""

jshell> s.length()
$4 ==> 6

但在终端中它是一个字符

➜  ~ echo -n '' | wc -m
       3

那么如何让Python与Atom保持一致?

背景:

我想在excel中写一些文本,但有些文本太大而且excel单元格有一个限制:最多32767个字符,所以我必须限制文本长度,例如文字[:32767]但我发现即使在这种情况下仍然无法打开生成的excel,因为如果文本中有特殊字符,其长度实际上超过32767。

4 个答案:

答案 0 :(得分:3)

Java和Python对字符串的长度有不同的定义。

  • 对于python,它是 Unicode代码点
  • 的数量
  • 对于Java,它是16位 Unicode代码单元的数量。

大于U + FFFF的字符(与大多数表情符号一样)每个代码点需要两个代码单元,一个是高代理,后面是一个低代理。

这与编码没有直接关系,但因为Java和Unicode规范最初仅限于U + 0000到U + FFFF范围(现在称为基本多语言平面,或BMP)。有关更详细的说明,请参阅Unicode Character Representations

答案 1 :(得分:2)

如果您只想计算Java或Atom将使用的长度,请将字符串编码为UTF-16LE(或UTF-16BE)并除以2以获得所需的16位代码单元数。

>>> s = ''  # Python 3.6
>>> len(s)
3
>>> len(s.encode('utf-16le'))//2
6
>>> s = 'abc123'
>>> len(s)
7
>>> len(s.encode('utf-16le'))//2
8

或者回到Python 3.3之前的Python,它像Java和Atom一样破碎......

>>> s = u''  # Python 2.7
>>> s
u'\U0001f44d'
>>> len(s)
2

答案 2 :(得分:1)

正如您在下面看到的,Python和Java对此特定字符的源代码有不同的解释:

Java/C++ = "\uD83D\uDC4D"
Python = u"\U0001F44D"

在这两个方面处理此问题的最佳方法是将特定语言中的它们转换为唯一标识符,例如:+1:或找到两种语言都能理解的唯一代码。

答案 3 :(得分:0)

现在为了正确生成excel,我采用以下方法:

1.text = text [:32767]

2.然后删除文本中的特殊字符

def filter_invalid_str(text):
    try:
        # UCS-4
        highpoints = re.compile(u'[\U00010000-\U0010ffff]')
    except re.error:
        # UCS-2
        highpoints = re.compile(u'[\uD800-\uDBFF][\uDC00-\uDFFF]')
    return highpoints.sub(u'', text)