【问题标题】:Encode a string to fixed-width unicode UCS-2 in Python在 Python 中将字符串编码为固定宽度的 unicode UCS-2
【发布时间】:2020-09-03 11:40:10
【问题描述】:

我需要一个固定宽度的字符串编码。据我了解,UCS-2 和 UCS-4(也就是 ASCII)就是这样的固定宽度编码。

据我了解,Python 仅通过s.encode('utf_16_le') 支持可变宽度的 UTF-16。这是真的吗?有没有一种简单的方法可以编码成 unicode 固定宽度编码?

上下文:我将一个字符串数组存储在原始字节中,并且需要一种方法来索引它以恢复原始字符串。当所有字符都是固定宽度时,索引计算更容易。

strings = ['asd', 'def']

# ascii
bytelens = list(map(len, strings))
bytes = ''.join(strings).encode('ascii')

# utf8
bytelens = []
bytes = bytearray()
for s in strings:
  e = s.encode('utf-8')
  bytelens.append(len(e))
  bytes.extend(e)

# i need bytelens to later recover original strings from the array bytes

如您所见,ASCII 变体非常简单,而 UTF-8 更复杂且速度慢 20%(可能是因为许多分配和函数调用)。真正的固定宽度 UCS-2 将是一个解决方案!

一个后续问题:我如何知道我的字符串是否包含 UCS-1 / UCS-2 / UCS-4 中的字符?对于 UCS-1,有 str.isascii。关于 UCS-2 的任何想法?

【问题讨论】:

标签: python unicode utf-16


【解决方案1】:

您正在混合各种概念。

在 Python 中,您可以只索引一个字符串(或一个数组)。每个字符的长度都没有关系。但同样在这种情况下,我应该警告您,一个字符不是单个/简单实体:如果您需要单个实体,您应该将更多字符放在一起(组合字符,例如重音等)。

UTF16 是可变宽度的,但它与 UCS2 相同,但适用于 UCS2 之外的字符。所以对于大多数事情来说,这并不重要,如果你有这样的字符,你只是在某个时候使用低和高代理(就像在许多其他仅支持 UCS2 的计算机语言上一样)。但这通常不是问题,因为您不应在随机位置拆分字符串,而应始终在实体的末尾。

UCS4 和 UTF-32 实际上是相同的编码:Unicode 代码指向 32 位数字。 (差异只是虚拟的,在某些定义上,不适用于 Unicode 字符[UCS 基于 ISO,它允许更多(更高)代码点,从不分配)

【讨论】:

  • "在 Python 中,您可以只索引一个字符串(或一个数组)。每个字符的长度都没有关系。"我将索引到一个大型 PyTorch 字节数组,然后恢复单个字符串。这样做是为了避免共享内存出现问题。有没有办法确保我的角色都适合 UCS-2?例如。我想确保(以一种快速的方式)我的所有字符都将被严格编码为两个字节。我想避免某些字符由 1 个字节和一些 - 由 2 个字节表示的情况。这会破坏索引计算。
  • 如果我有办法恢复 UTF-16 编码的字节长度,我的问题也将得到解决。
  • 如果我理解正确,我应该 1) 确保所有字符都适合 UCS-2,2) 可以将字节数计算为 [len(s) * 2 for s in strings],对吗?我知道存在 str.isascii。有 str.isucs2 吗?我找不到它。并且遍历所有字符可能会很慢。
  • 对于第一个问题:这取决于您如何读取字节。 Python 字符串使用“固定”长度编码,它可能是可变的。换句话说:在一个字符串中,每个字符都有相同的长度,但是如果一个字符串只是 ASCII [或 Latin1],python 只使用一个字节,如果可以使用 UCS2,它使用 UCS2,否则它将使用 UTF-32 .每个字符串可能使用不同的“子编码”,但字符串中的每个字符都有相同的长度
  • 而且因为字符串是只读的,所以它永远不会引起问题。 [在不生成新字符串的情况下,您永远不能更改字符串中间的字符]
猜你喜欢
  • 2011-02-16
  • 2018-01-28
  • 2015-10-05
  • 1970-01-01
  • 1970-01-01
  • 2012-01-15
  • 1970-01-01
  • 1970-01-01
  • 2010-12-02
相关资源
最近更新 更多