【问题标题】:How can there be a fixed width Unicode encoding?怎么会有固定宽度的 Unicode 编码?
【发布时间】:2015-10-05 08:23:59
【问题描述】:

在阅读 Unicode 时,我多次听说 UTF-32 是一种固定宽度编码。

采用固定宽度编码来表示“将源符号映射到一组比特的代码”,并且假设所讨论的源符号是 Unicode 代码点,这一切都是有道理的。但是,如果您认为源符号的底层语言是字素,事情就会变得复杂得多。

所以我的问题是,就字素而言,UTF-32 真的是固定长度编码吗?如果没有,在这个意义上是否有可能的固定长度编码?

【问题讨论】:

  • 阅读:The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)。是的,UTF-16 和 UTF-32 都是固定宽度。 UTF-8(也许令人惊讶)不是。
  • @paulsm4 几个月前我读过它。我喜欢它作为 Unicode 入门指南,但我不明白它如何回答我的第二个问题。
  • @paulsm4: UTF-16 并不是真正的固定宽度;一些 Unicode 字符(代码点)是一个 16 位代码单元,另一些则需要两个 16 位代码单元。就像 UTF-8 不是固定宽度一样;一些 Unicode 字符(代码点)需要一个 8 位代码单元,而另一些则需要两个、三个甚至四个 8 位代码单元。另一方面,UTF-32 是固定宽度;所有字符(代码点)都被编码在一个 32 位代码单元中。
  • 属于程序员堆栈交换。这个问题更多的是理论,而不是问题解决方案。 programmers.stackexchange.com
  • “认为源符号的底层语言是字素”是什么意思?如果它使事情变得更复杂,那么这样思考有什么好处?确实,这样想有什么好处?如果您的意思与“它可能需要多个 Unicode 代码点来获得具有相关变音符号(组合标记、杂项)的完整字符”有关,那么是的,即使 UTF-32 也不一定是固定宽度,也没有固定宽度Unicode 编码。

标签: unicode encoding character-encoding utf-32


【解决方案1】:

其中一个 cmets 引用了 Joel Spolsky 的 The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!) 文章,该文章写于 2003 年。当时,它起到了警钟的作用(在某些地方可能仍然如此)。然而,它并非没有(次要但重要的)技术问题——尽管整体论点(“您需要了解 Unicode,并且您需要知道字符串的编码方式”)仍然有效。然后评论继续:

是的,UTF-16 和 UTF-32 都是固定宽度。 UTF-8 … 不是。

UTF-16 并不是真正的固定宽度;一些 Unicode 代码点是一个 16 位代码单元,而另一些则需要两个 16 位代码单元——就像 UTF-8 不是固定宽度一样;一些 Unicode 代码点需要一个 8 位代码单元,其他需要两个、三个甚至四个 8 位代码单元(但不是五个或六个,尽管 Joel 的文章中提到了这种可能性)。另一方面,UTF-32 是固定宽度;所有 Unicode 代码点都可以编码在一个 32 位代码单元中。 (实际上,最大可能的 Unicode 码位是 U+10FFFF,所以 Unicode 是一个 21 位的代码集,尽管它并不使用 21 位的所有可能组合。)

然而,码位并不等同于字符,更不用说字素了。 Unicode 常见问题解答中有一个关于 Characters and Combining Marks 的部分讨论了字素,引用了 glossary 定义。

对于最终用户所认为的字符而言,更好的词是字素(如 Unicode 词汇表中所定义):在特定书写系统的上下文中最小的独特书写单位。

字素不一定是组合字符序列,组合字符序列也不一定是字素。

Q: How are characters counted when measuring the length or position of a character in a string?

答:计算 Unicode 字符串中“字符”的长度或位置可能有点复杂,因为有四种不同的方法可以计算,加上组合字符可能引起的混乱。正确选择使用哪种计数方法取决于计数的内容以及计数或位置的用途。

在这里解决问题:

如果您的意思是“可能需要多个 Unicode 代码点才能获得带有相关变音符号(组合标记等)的完整字符(字素)”,那么是的,即使 UTF-32 也不一定是固定宽度并且 Unicode 没有固定宽度的编码。

UTF-32 对每个 Unicode 码位采用固定宽度编码,但由于创建一个完整的字素可能需要多个码位,因此即使 UTF-32 也没有码位和字素之间的 1:1 映射。

当然,您也可以在 SO 上的一些 cmets 中找到有趣的字符堆栈。例如:



@̮̘̮̜̤͓͓̓ͪ̓͆͗̑ṷ̫̠̤̙̻͚̗ͭs̹͓̰̫͉̺̈̏̽̅̑ͩ̇̓̉e͖̝̦̦̿rən̹͖̥ͥͦͤ̍͊̏ä͇͖͚͖͊m̭͇͆͋̋͒e̫̠͇̰̦̹̫̠͇̰̦̹͔͖̫̬̗̪̪̳͔͖̫̬̗̪̪̳̜̥̣̬̮͈̮͉̣̟̪̪̜̦̪͗͋̓̿͒͗͋̓̿͒ͧ̄ͫͧ̄ͫ͒̄ͪ͊̿̍ͫ͋͐̑͗͗̈ͣ͊ḫ̘̯͈̠̞̜̦̪͒ͯ͗͗̈ͣ͊ḫ̘̯͈̠̞̣͕͚̗̠͖̫͇̰̝̺͒ͯ̆͌͒̓͛͊ͧͫ͛.̖̩̭͇̭͔̹̈̇͐ͬͦͦͨ̾̇.͍̪̣͍̪̣ͬͬ.̞͍̥̪̺̤̣̜͍̪̣̞͍̥̪̺̤̣̜͍̪̣̘͓͔̟͔͍̘͓͔̟͔͍̘͓͔̟͔͍̫̼̫̜̦̪͆ͫ̈͑ͦ͑͑ͬ͆ͫ̈͑ͦ͑͑ͬ̏ͣͦ̓̓̏ͣͦ̓̓̏ͣͦ̓̓ͮ͌̄ͤ̿̈͆͗͗̈ͣ͊ḫ̘̯͈̠̞͇̰̝̺͒ͯ͊ͧͫ͛。

Why/how do "Zalgo pings" work?

How does Zalgo text work?



ȩ̸҉̟͎͚̹͚̙̟̖x̨͙̰͕̖͉̼̜̦̟͈ą̷̘͕͈̹͓̣̮̼̣̠̹c̼͙̠̭̫̰͈͍̮͢͡ţ̢̛̠͇̬̖̟̺͈̻̣͙͈̼͍̘lȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱuȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱȱ



当然,您看到的内容取决于浏览器中 Unicode 支持的质量(反过来,这部分取决于操作系统的质量支持)。我在两台运行不同版本 Firefox 的不同 Mac 上看到了不同的结果,即使它们运行的​​是相同的基本 O/S 版本(10.10.4 Yosemite)。

这些示例中的第二个可以从 UTF-8 解码为以下 Unicode 代码点序列 - 它在磁盘上只有 700 个字节:

0xC8 0xA8 = U+0228
0xCC 0xB8 = U+0338
0xD2 0x89 = U+0489
0xCC 0x9F = U+031F
0xCD 0x8E = U+034E
0xCD 0x9A = U+035A
0xCC 0xB9 = U+0339
0xCD 0x9A = U+035A
0xCC 0x99 = U+0319
0xCC 0x9F = U+031F
0xCC 0x96 = U+0316
0x78 = U+0078
0xCC 0xA8 = U+0328
0xCD 0x99 = U+0359
0xCC 0xB0 = U+0330
0xCD 0x95 = U+0355
0xCC 0x96 = U+0316
0xCD 0x89 = U+0349
0xCC 0xBC = U+033C
0xCC 0x9C = U+031C
0xCC 0xB2 = U+0332
0xCC 0xA6 = U+0326
0xCC 0x9F = U+031F
0xCD 0x88 = U+0348
0xCC 0x81 = U+0301
0xCD 0x85 = U+0345
0xCD 0x85 = U+0345
0xC4 0x85 = U+0105
0xCC 0xB7 = U+0337
0xCC 0x98 = U+0318
0xCD 0x95 = U+0355
0xCD 0x88 = U+0348
0xCC 0xB9 = U+0339
0xCD 0x93 = U+0353
0xCC 0xA3 = U+0323
0xCC 0xAE = U+032E
0xCC 0xBC = U+033C
0xCC 0xA3 = U+0323
0xCC 0xA0 = U+0320
0xCC 0xB9 = U+0339
0xCC 0x81 = U+0301
0x63 = U+0063
0xCC 0xBC = U+033C
0xCD 0x99 = U+0359
0xCC 0xA0 = U+0320
0xCC 0xAD = U+032D
0xCC 0xAB = U+032B
0xCC 0xB0 = U+0330
0xCD 0x88 = U+0348
0xCD 0x8D = U+034D
0xCC 0xAE = U+032E
0xCD 0xA2 = U+0362
0xCD 0xA1 = U+0361
0xC5 0xA3 = U+0163
0xCC 0xA2 = U+0322
0xCC 0x9B = U+031B
0xCC 0xA0 = U+0320
0xCD 0x87 = U+0347
0xCC 0xAC = U+032C
0xCC 0x96 = U+0316
0xCC 0x9F = U+031F
0xCC 0xBA = U+033A
0xCD 0x88 = U+0348
0xCC 0xB2 = U+0332
0xCC 0xBB = U+033B
0xCC 0xA3 = U+0323
0xCC 0xB2 = U+0332
0xCD 0x99 = U+0359
0xCD 0x88 = U+0348
0xCC 0xBC = U+033C
0xCD 0x8D = U+034D
0xCC 0x98 = U+0318
0xCC 0xB1 = U+0331
0xCD 0x85 = U+0345
0x6C = U+006C
0xCC 0xB6 = U+0336
0xCD 0x98 = U+0358
0xE2 0x80 0x8C = U+200C
0xE2 0x80 0x8B = U+200B
0xCC 0xB7 = U+0337
0xCC 0xA8 = U+0328
0xCC 0xB2 = U+0332
0xCD 0x99 = U+0359
0xCD 0x96 = U+0356
0xCC 0xBB = U+033B
0xCC 0xB2 = U+0332
0xCC 0x97 = U+0317
0xCC 0xA6 = U+0326
0xCD 0x9A = U+035A
0xCD 0x99 = U+0359
0xCC 0xAE = U+032E
0xCD 0xA0 = U+0360
0x79 = U+0079
0xCC 0xAD = U+032D
0xCC 0x96 = U+0316
0xCC 0xB0 = U+0330
0xCD 0x9A = U+035A
0xCC 0x9E = U+031E
0xCC 0xA3 = U+0323
0xCC 0x97 = U+0317
0xCC 0xB3 = U+0333
0xCC 0xA0 = U+0320
0xCD 0x95 = U+0355
0xCC 0xBB = U+033B
0xCC 0xBC = U+033C
0xCD 0xA1 = U+0361
0xCD 0x85 = U+0345
0x21 = U+0021
0xCC 0x9B = U+031B
0xCD 0x96 = U+0356
0xCC 0xAE = U+032E
0xCD 0x94 = U+0354
0xCD 0x8D = U+034D
0xCC 0xB0 = U+0330
0xCD 0x89 = U+0349
0xCD 0xA2 = U+0362
0x20 = U+0020
0xCC 0xAD = U+032D
0xCC 0x99 = U+0319
0xCC 0x96 = U+0316
0xCD 0x94 = U+0354
0xCC 0xA9 = U+0329
0xCC 0x97 = U+0317
0xCC 0xA0 = U+0320
0xCD 0x95 = U+0355
0xCC 0xA6 = U+0326
0xCC 0xAC = U+032C
0xCD 0x93 = U+0353
0xCD 0x9E = U+035E
0xCD 0x9D = U+035D
0xCD 0x85 = U+0345
0x4F = U+004F
0xD2 0x89 = U+0489
0xD2 0x89 = U+0489
0xCC 0xA3 = U+0323
0xCC 0x9C = U+031C
0xCC 0xBA = U+033A
0xCC 0xAA = U+032A
0xCC 0xB3 = U+0333
0xCD 0x95 = U+0355
0xCC 0x96 = U+0316
0xCD 0x94 = U+0354
0xCC 0xA0 = U+0320
0xCD 0x99 = U+0359
0xCD 0x8E = U+034E
0xCD 0x95 = U+0355
0xCC 0x99 = U+0319
0xCC 0xA6 = U+0326
0xCD 0x85 = U+0345
0x6E = U+006E
0xCC 0xA9 = U+0329
0xCD 0x93 = U+0353
0xCD 0x96 = U+0356
0xCC 0x9D = U+031D
0xCC 0x9F = U+031F
0xCC 0xAD = U+032D
0xCD 0x99 = U+0359
0xCD 0x99 = U+0359
0xCD 0x93 = U+0353
0xCD 0x9A = U+035A
0xCC 0xBC = U+033C
0xCD 0x96 = U+0356
0xCD 0x96 = U+0356
0xCD 0x9C = U+035C
0xCD 0x9E = U+035E
0xC8 0xA9 = U+0229
0xCC 0xA7 = U+0327
0xCC 0xAC = U+032C
0xCC 0xB1 = U+0331
0xCC 0xA6 = U+0326
0xCC 0xA0 = U+0320
0xCC 0x99 = U+0319
0xCC 0xA5 = U+0325
0xCD 0x87 = U+0347
0xCD 0x94 = U+0354
0xCC 0xAA = U+032A
0xCC 0x81 = U+0301
0x20 = U+0020
0xD2 0x89 = U+0489
0xCC 0xB8 = U+0338
0xCC 0x97 = U+0317
0xCC 0xA6 = U+0326
0xCD 0x87 = U+0347
0xCC 0xB0 = U+0330
0xCC 0xAA = U+032A
0xCC 0xB0 = U+0330
0xCC 0xAD = U+032D
0xCC 0x98 = U+0318
0xCC 0xB9 = U+0339
0xCD 0x98 = U+0358
0xCD 0xA2 = U+0362
0x69 = U+0069
0xCC 0xB4 = U+0334
0xCD 0x9E = U+035E
0xCD 0x8F = U+034F
0xCC 0xA9 = U+0329
0xCC 0xA4 = U+0324
0xCC 0xB9 = U+0339
0xCC 0x97 = U+0317
0xCC 0x96 = U+0316
0xCC 0xB0 = U+0330
0xCD 0x8E = U+034E
0xCC 0x96 = U+0316
0xCC 0xB2 = U+0332
0xCC 0xB2 = U+0332
0xCC 0x98 = U+0318
0xCD 0x93 = U+0353
0xCC 0x97 = U+0317
0xCC 0xAF = U+032F
0xCD 0x9A = U+035A
0xCC 0x9E = U+031E
0xCD 0x96 = U+0356
0xCC 0xA5 = U+0325
0xCC 0xBB = U+033B
0xCD 0x9D = U+035D
0x73 = U+0073
0xCD 0x9E = U+035E
0xD2 0x89 = U+0489
0xCC 0xB2 = U+0332
0xCD 0x88 = U+0348
0xCC 0x99 = U+0319
0xCC 0xB9 = U+0339
0xCC 0xA4 = U+0324
0xCC 0xAB = U+032B
0xCD 0x87 = U+0347
0x20 = U+0020
0xCD 0x9A = U+035A
0xCC 0xAD = U+032D
0xCD 0x8E = U+034E
0xCD 0x89 = U+0349
0xCC 0xA0 = U+0320
0xCC 0xBA = U+033A
0xCD 0x89 = U+0349
0xCC 0xAE = U+032E
0xCC 0x9E = U+031E
0xCC 0xBB = U+033B
0xCC 0xA3 = U+0323
0xCC 0xB0 = U+0330
0xCC 0xBA = U+033A
0xCC 0x96 = U+0316
0xCD 0x96 = U+0356
0xCC 0x80 = U+0300
0xCC 0x81 = U+0301
0xCD 0xA2 = U+0362
0xCD 0x9E = U+035E
0x65 = U+0065
0xCC 0xB7 = U+0337
0xCC 0xAA = U+032A
0xCC 0xAD = U+032D
0xCC 0xAF = U+032F
0xCC 0xBC = U+033C
0xCD 0x93 = U+0353
0xCD 0x8E = U+034E
0xCC 0xB9 = U+0339
0xCC 0xA0 = U+0320
0xCD 0x96 = U+0356
0xCC 0xB2 = U+0332
0xCD 0x94 = U+0354
0xCC 0xAA = U+032A
0xCD 0x88 = U+0348
0xCC 0xA6 = U+0326
0xCD 0x88 = U+0348
0xCC 0xB1 = U+0331
0xCD 0x8D = U+034D
0xCC 0xAD = U+032D
0xCC 0xA9 = U+0329
0xCD 0xA0 = U+0360
0xC5 0x86 = U+0146
0xCD 0x9E = U+035E
0xD2 0x89 = U+0489
0xCC 0xAE = U+032E
0xCC 0xB3 = U+0333
0xCD 0x93 = U+0353
0xCD 0x99 = U+0359
0xCD 0x88 = U+0348
0xCC 0xBC = U+033C
0xCD 0x89 = U+0349
0xCC 0xAC = U+032C
0xCD 0x95 = U+0355
0xCD 0x88 = U+0348
0xCC 0xBA = U+033A
0xCD 0x88 = U+0348
0xCC 0xAD = U+032D
0xCC 0xA9 = U+0329
0xCC 0xAA = U+032A
0x6F = U+006F
0xCD 0x87 = U+0347
0xCC 0x97 = U+0317
0xCC 0xB1 = U+0331
0xCC 0xA0 = U+0320
0xCC 0xB1 = U+0331
0xCC 0xA0 = U+0320
0xCC 0xAF = U+032F
0xCC 0x95 = U+0315
0xCD 0xA2 = U+0362
0x75 = U+0075
0xCC 0xB8 = U+0338
0xCC 0xB3 = U+0333
0xCC 0xA6 = U+0326
0xCC 0xA9 = U+0329
0xCC 0xB3 = U+0333
0xCC 0xAB = U+032B
0xCC 0x96 = U+0316
0xCC 0x9C = U+031C
0xCD 0x85 = U+0345
0xE2 0x80 0x8C = U+200C
0xE2 0x80 0x8B = U+200B
0xC7 0xB5 = U+01F5
0xCC 0xA2 = U+0322
0xCC 0xB2 = U+0332
0xCC 0xA3 = U+0323
0xCD 0x8E = U+034E
0xCC 0xAE = U+032E
0xCC 0xAE = U+032E
0xCC 0xBC = U+033C
0xCC 0xAB = U+032B
0xCC 0xA5 = U+0325
0xCC 0xA0 = U+0320
0xCD 0x99 = U+0359
0xCC 0xB1 = U+0331
0xCC 0x9D = U+031D
0xCC 0x98 = U+0318
0xCD 0x95 = U+0355
0xCD 0x8E = U+034E
0xCC 0xB3 = U+0333
0xCC 0x9C = U+031C
0xCC 0xB2 = U+0332
0xCC 0x96 = U+0316
0x68 = U+0068
0xCC 0xB8 = U+0338
0xCC 0x9B = U+031B
0xCC 0xA9 = U+0329
0xCD 0x9A = U+035A
0xCC 0xAE = U+032E
0xCC 0xA4 = U+0324
0xCC 0x96 = U+0316
0xCC 0xB9 = U+0339
0xCD 0x99 = U+0359
0x2E = U+002E
0xCC 0xB6 = U+0336
0xCC 0xA8 = U+0328
0xCC 0xB3 = U+0333
0xCC 0x96 = U+0316
0xCC 0xA0 = U+0320
0xCC 0x97 = U+0317
0xCC 0xBC = U+033C
0xCC 0xA9 = U+0329
0xCD 0x95 = U+0355
0xCD 0x87 = U+0347
0xCD 0x89 = U+0349
0xCD 0x93 = U+0353
0xCC 0x9F = U+031F
0xCC 0xA6 = U+0326
0xCD 0x9C = U+035C
0xCD 0x9E = U+035E
0xCD 0x85 = U+0345
0x0A = U+000A

破译其中的哪些部分是字素变得很棘手,但很明显,对于所有堆叠的字符,这不是每个字素的固定数据量,并且没有理智的方法可以使 Unicode 在每个固定宽度编码下工作字素,因为正如“Zalgo”示例所示,组合标记基本上可以按任意顺序组合。

第二个“Zalgo”示例中的第一个字素包含:

0xC8 0xA8 = U+0228    LATIN CAPITAL LETTER E WITH CEDILLA
0xCC 0xB8 = U+0338    COMBINING LONG SOLIDUS OVERLAY
0xD2 0x89 = U+0489    CYRILLIC COMBINING MILLIONS SIGN
0xCC 0x9F = U+031F    COMBINING PLUS SIGN BELOW
0xCD 0x8E = U+034E    COMBINING UPWARDS ARROW BELOW
0xCD 0x9A = U+035A    COMBINING DOUBLE RING BELOW
0xCC 0xB9 = U+0339    COMBINING RIGHT HALF RING BELOW
0xCD 0x9A = U+035A    COMBINING DOUBLE RING BELOW
0xCC 0x99 = U+0319    COMBINING RIGHT TACK BELOW
0xCC 0x9F = U+031F    COMBINING PLUS SIGN BELOW
0xCC 0x96 = U+0316    COMBINING GRAVE ACCENT BELOW

下一个代码点是 U+0078 LATIN SMALL LETTER X,新字素的开始。几个组合标记在该列表中分别出现多次。

【讨论】:

  • Joel 的文章读起来可能很棒,但遗憾的是,它充满了您指出的小错误。 (在我的脑海中也有人声称 UTF-8 达到 6 个字节,这已经严重过时了)
  • @R.MartinhoFernandes 是的,这就是我不推荐它的原因,尽管我很遗憾不推荐。我不明白他为什么不修复它。
  • @tchrist:我根据您的评论(以及 R. Martinho Fernandes 的评论)部分修改了对 Joel 文章的评论。它提到了 UTF-7,我很长时间没有看到过认真的讨论或使用。维基百科说UTF-7 是一些 RFC 定义的实验性协议,这些 RFC 从未正式成为 Internet 标准,UTF-7 也从来不是 Unicode 标准,显然 Internet 邮件联盟建议不要使用它。
  • 我想您可能想明确指出为什么固定长度编码是不可能的,即您可以无限堆叠组合标记!但围绕一个漂亮的答案,我很快就会将其标记为已接受。
【解决方案2】:

UTF-32 是一种固定宽度的编码,顺便说一下,它是唯一将 DWORD 值直接映射到 Unicode 代码点的 Unicode 编码。但是有一个值的限制,最大值是 0x10FFFF 并且整个高和低代理范围在 UTF-32 内都是无效的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-03
    • 1970-01-01
    • 2018-01-28
    • 1970-01-01
    • 2011-10-29
    • 2012-02-21
    相关资源
    最近更新 更多