2

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

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

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

4

2 回答 2

5

其中一条评论引用了 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 FAQ 有一个关于字符和组合标记的部分讨论字素,参考词汇表定义。

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

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

问:在测量字符串中字符的长度或位置时,如何计算字符?

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

要解决这里的问题:

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

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

当然,你也可以在 SO 的一些评论中找到有趣的字符栈。例如:



@̮̘̮̜̤͓͓̓ͪ̓͆͗̑ṷ̫̠̤̙̻͚̗ͭS̹͓̰̫͉̲̺̈̏̽̅̑ͩS̹͓̰̫͉̲̺̈̏̽̅̑ͩe͖̝̦̦̿e͖̝̦̦̿e͖̝̦̦̿n̹͖̥ͥͦͤ̍͊̏um̭͇̂͆͋̋͒e̫̠͇̰̱̦̹͗͋̓̿͒e̫̠͇̰̱̦̹͗͋̓̿͒b̜̥̣̬̮͈͒̄ͪ͊l̮͉̣̟̪̪̿̍ͫ͋͐̑a̜̦̪͗͗̈́ͣ͊ḫ̘̯͈̠̞͒ͯb̖̣͇̖̦̃̑ͬͭͥb̖̣͇̖̦̃̑ͬͭͥl͔͍͚͕̲̪̼͎̫̼̫ͧͮ͌̄ͤ̿̈͆h̘͓͔̟͔͍̏ͣͦ̓̓



“Zalgo pings”为什么/如何工作?

Zalgo 文本如何工作?



ȩ̸҉̟͎͚̹͚̙̟̖x̨͙̰͕̖͉̼̜̲̦̟͈́ͅͅą̷̘͕͈̹͓̣̮̼̣̠̹́c̼͙̠̭̫̰͈͍̮͢͡ţ̢̛̠͇̬̖̟̺͈̲̻̣̲͙͈̼͍̘̱ͅl̶͘‌ ̷̨̲͙͖̻̲̗̦͚͙̮͠ y̭̖̰͚̞̣̗̳̠͕̻̼͡ͅ!̛̛͖̮͔͍̰͉͖̮͔͍̰͉͢͢





当然,您看到的内容取决于浏览器中 Unicode 支持的质量(这又部分取决于 O/S 支持的质量)。我在运行相当不同版本的 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,新字形的开始。几个组合标记在该列表中分别出现多次。

于 2015-07-16T06:04:50.747 回答
0

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

于 2015-08-26T09:15:27.667 回答