我要问一个可能引起争议的问题:“是否应该将最受欢迎的一种编码UTF-16视为有害?”

为什么要这样做我问这个问题吗?

有多少程序员知道UTF-16实际上是可变长度编码这一事实?我的意思是说,代表代理对的代码点包含多个元素。

我知道;许多应用程序,框架和API使用UTF-16,例如Java的String,C#的String,Win32 API,Qt GUI库,ICU Unicode库等。但是,所有这些都在处理中存在许多基本的错误。 BMP中的字符数(应使用两个UTF-16元素编码的字符)。例如,尝试编辑以下字符之一:


𝄞(U + 1D11E)音乐符号G CLEF

𝕥(U + 1D565)数学双打击小T

𝟶(U + 1D7F6)数学单点数字零

𠂊(U + 2008A)汉字


您可能会错过一些字体,具体取决于您安装的字体。这些字符都在BMP(基本多语言平面)之外。如果看不到这些字符,也可以尝试在Unicode字符参考​​中查看它们。例如,尝试在Windows中创建包含这些字符的文件名;例如,在Windows中创建包含这些字符的文件名。请尝试使用“退格键”删除这些字符,以查看它们在使用UTF-16的不同应用程序中的行为。我做了一些测试,结果却很糟糕:


Opera在编辑它们时遇到了问题(删除需要按两下退格键)
记事本无法正确处理它们(删除需要按2下的退格键)
在Windows对话框中编辑文件名时要打断(删除需要按2下的退格键)
所有QT3应用程序都无法处理它们-显示两个空的正方形而不是一个符号。
当在某些平台上直接使用u'X'!=unicode('X','utf-16')时,如果BMP之外的字符中的X字符,Python会错误地编码此类字符。如果直接将它们作为Unicode字符编辑(这些字符使用HTML Unicode转义符显示),则从文本中删除这些字符。

受MaxLength限制,WinForms TextBox可能会生成无效的字符串。

似乎在许多使用UTF-16的应用程序中都非常容易发现这种错误。

所以...您认为UTF-16应该被认为是有害的吗?

评论

不太正确。我解释一下,如果您写“שָׁ”由“ש”,“ָ”和“ׁ”,vovel组成的复合字符,那么删除其中每个是合乎逻辑的,则按“退格”,并在按“ del”时删除所有字符,包括符。但是,您永远不会产生非法的文本状态-非法的代码点。因此,当您按Backspace键并获取非法文本时,这种情况是不正确的。

CiscoIPPhone:如果一个错误“被许多不同的人报告了几次不同的时间”,然后几年后,一个开发人员在开发博客上写了一个“信不信由你,此行为主要是故意的!”我倾向于认为这可能不是有史以来最好的设计决策。 :-)仅仅因为它是故意的,并不意味着它不是错误。

很棒的帖子。 UTF-16确实是“两全其美”:UTF8是可变长度的,涵盖所有Unicode,要求在原始代码点之间进行转换算法,并限制为ASCII,并且没有字节顺序问题。 UTF32是固定长度的,不需要进行转换,但是会占用更多空间并存在字节顺序问题。到目前为止,您可以在内部使用UTF32,并使用UTF8进行序列化。但是UTF16没有任何好处:它与字节序有关,长度可变,占用大量空间,与ASCII不兼容。正确处理UTF16所需的工作可以在UTF8上花费更好。

@Ian:UTF-8与UTF-8没有相同的警告。您不能在UTF-8中使用代理。 UTF-8不会伪装成不伪装的东西,但是大多数使用UTF-16的程序员都错误地使用了它。我知道。我一次又一次地看着他们。

同样,UTF-8也不存在问题,因为每个人都将其视为可变宽度编码。 UTF-16出现问题的原因是因为每个人都将其视为固定宽度编码。

#1 楼


这是一个旧答案。
有关最新更新,请参见UTF-8。


意见:是的,应该将UTF-16视为有害。它存在的根本原因是因为一段时间以前,人们曾经误导了Widechar将成为现在的UCS-4。它应被视为唯一有用的文本编码。可以认为,程序,网页和XML文件,OS文件名以及其他计算机对计算机文本接口的源代码应该永远都不存在。但是,当这样做的时候,文本不仅适合人类读者。

另一方面,UTF-8开销是一笔不小的代价,同时具有明显的优势。诸如与仅通过char*传递字符串的无意识代码兼容的优点。这是一件了不起的事。与UTF-8中相比,UTF-16中的SHORTER有用的字符很少。

我相信所有其他编码最终都会消失。这涉及到MS-Windows,Java,ICU,python停止使用它们作为收藏夹。经过长期的研究和讨论,我公司的开发约定禁止在OS API调用之外的任何地方使用UTF-16,尽管这对我们的应用程序中性能的重要性以及我们使用Windows的事实也是如此。开发转换函数是为了将始终假定的UTF8 std::string转换为Windows本身不正确支持的本机UTF-16。说:在所有地方使用相同的编码有很大的优势,我认为没有足够的理由这样做。特别是,我认为将wchar_t添加到C ++中是一个错误,对C ++ 0x的Unicode添加也是如此。但是,STL实现必须要求将每个std::stringchar*参数都视为与unicode兼容。

我也反对“使用您想要的”方法。我认为没有这种自由的理由。文本主题上有足够的混乱,导致所有这些损坏的软件。综上所述,我坚信程序员必须最终就UTF-8达成共识,这是一种正确的方法。 (我来自一个不讲阿拉伯语的国家,并且在Windows上长大,所以我最后一次基于宗教理由会攻击UTF-16。)

我想分享更多有关如何在Windows上执行文本以及为编译时检查的unicode正确性,易用性和更好的多平台性向其他所有人的推荐的信息。该建议与通常推荐的在Windows上使用Unicode的正确方法大不相同。然而,对这些建议的深入研究得出了相同的结论。这样就可以:


不要在接受UTF-16的API的相邻点以外的任何地方使用wchar_tstd::wstring
请勿使用_T("")L"" UTF-16文字(作为UTF-16弃用的一部分,应将IMO从标准中删除)。
请勿使用类型,函数或其派生类。对_UNICODE常数敏感的变量,例如LPTSTRCreateWindow()
但是,始终定义_UNICODE,以避免将char*字符串传递给WinAPI进行静默编译。

std::stringschar*被认为在程序中的任何地方UTF-8(如果未另外说明)
尽管您可以将char *或字符串文字传递给std::string,但我所有的字符串都是convert(const std::string &)。绝不要接受LPWSTRLPTSTR的那些。以这种方式传递参数:

::SetWindowTextW(Utils::convert(someStdString or "string litteral").c_str())


(该策略使用下面的转换函数。)


使用MFC字符串:

CString someoneElse; // something that arrived from MFC. Converted as soon as possible, before passing any further away from the API call:

std::string s = str(boost::format("Hello %s\n") % Convert(someoneElse));
AfxMessageBox(MfcUtils::Convert(s), _T("Error"), MB_OK);



在Windows上使用文件,文件名和fstream:


切勿将LPSTRstd::string文件名参数传递给const char*系列。 MSVC STL不支持UTF-8参数,但具有非标准扩展名,应按以下方式使用: br />
当MSVC对fstream的态度发生变化时,我们将必须手动删除转换。

此代码不是多平台的,将来可能需要手动更改
有关详细信息,请参阅std::string Unicode研究/讨论案例4215。如有必要,请使用上述std::wstring和WinAPI约定。




std::ifstream ifs(Utils::Convert("hello"),
                  std::ios_base::in |
                  std::ios_base::binary);


评论


我不同意在许多亚洲语言中,utf16优于utf8的优势完全支配了您的观点。希望日文,泰文,中文等放弃这种编码是幼稚的。字符集之间有问题的冲突是,字符集看起来大体相似,除了区别。我建议标准化:固定7位:iso-irv-170; 8位变量:utf8; 16位变量:utf16;固定的32位:ucs4。

–查尔斯·斯图尔特
2009年12月9日15:24

@查尔斯:谢谢您的输入。的确,UTF-8中的某些BMP字符比UTF-16中的字符长。但是,让我们面对现实:问题不是BMP汉字占用的字节数,而是出现的软件设计复杂性。如果中国程序员无论如何都要设计可变长字符,那么与系统中的其他变量相比,UTF-8似乎仍然是一个很小的代价。如果空间非常重要,他可能会使用UTF-16作为压缩算法,但即便如此,它也不会与LZ相匹配,并且在LZ或其他通用压缩之后,它们都需要大约相同的大小和熵。

–帕维尔·拉齐维洛夫斯基(Pavel Radzivilovsky)
09年12月9日在18:04

我基本上要说的是,使用One编码还可以与现有char *程序兼容并且目前在所有应用中都最受欢迎的一种简化方式是无法想象的。这几乎就像在过去的“纯文本”时代一样。要打开一个带有名称的文件吗?无需关心您正在执行哪种unicode,等等。我建议我们,开发人员,将UTF-16限制在非常特殊的严重优化情况下,其中很少的性能值得数月的工作。

–帕维尔·拉齐维洛夫斯基(Pavel Radzivilovsky)
09年12月9日在18:08

选择内部使用UTF-8时,Linux有一个特定的要求:与Unix的兼容性。 Windows不需要它,因此,当开发人员实现Unicode时,他们添加了几乎所有处理文本的函数的UCS-2版本,并使多字节函数简单地转换为UCS-2并调用其他函数。随后,他们用UTF-16取代了UCS-2。另一方面,Linux保持8位编码,因此使用UTF-8,因为在这种情况下,它是正确的选择。

–迈尔奇亚(Mircea Chirea)
2010-3-17在17:56

@Pavel Radzivilovsky:顺便说一句,您关于“我相信所有其他编码最终都会消失。这涉及到MS-Windows,Java,ICU,python不再使用它们作为他们的最爱。”并且“特别是,我认为将wchar_t添加到C ++中是一个错误,对C ++ Ox的unicode添加也是如此。”要么很天真,要么很自大。这是来自在家使用Linux进行编码并且对UTF-8字符感到满意的人。坦率地说:这不会发生。

–paercebal
2010年9月4日在12:28

#2 楼

Unicode代码点不是字符!有时它们甚至都不是字形(视觉形式)。 (一个看起来像“ iii”的单个字符。)
像“á”这样的带重音符号的字符可以表示为单个组合字符“ \ u00e1”,也可以表示为字符和分隔的变音符号“ \ u0061 \ u0301”。
像希腊小写字母sigma这样的字符,其单词位置的中间(“σ”)和结尾(“ς”)具有不同的形式,但应将其视为搜索的同义词。
Unicode任意连字符U + 00AD,它可能会或可能不会在视觉上显示出来(取决于上下文),并且在语义搜索中会被忽略。成为专家,自己写一个。如果您只是在计数代码点,那您就处于犯罪状态。

评论


这个。这非常。 UTF-16可能会引起问题,但是即使在整个过程中使用UTF-32也会(也将会)给您带来问题。

– bcat
10 Dec 24'0:48

什么是角色?您可以将代码点定义为字符,并且可以正常使用。如果您指的是用户可见的字形,那是另外一回事。

–基督
2011年8月11日14:54

@tchrist肯定可以分配定义很好的空间,但是还有其他用途吗?没那么多。如果将组合字符作为唯一字符来处理(即删除或“采用前N个字符”操作),则会出现奇怪和错误的行为。如果一个代码点与至少另一个代码点结合在一起仅具有含义,那么您将无法以任何明智的方式自行处理它。

– Voo
2011年8月15日在15:28

@Pacerier,聚会晚了,但我必须对此发表评论。某些语言具有大量的变音符号组合(例如越南语,即mệtđừ)。在每个变音符号中使用组合而不是一个字符非常有帮助。

–asthasr
2012年4月20日在21:23

关于术语的小注释:代码点确实对应于unicode字符; Daniel在这里谈论的是用户感知的字符,它们对应于unicode字素簇

– Christophh
2012年4月21日在11:58



#3 楼

使用哪种Unicode转换形式(UTF)有一个简单的经验法则:
-utf-8用于存储和通信
-utf-16用于数据处理
-您可能会喜欢utf-32(如果您使用的大多数平台API是utf-32(在UNIX世界中很常见)。)

当今大多数系统都使用utf-16(Windows,Mac OS,Java,.NET,ICU) ,Qt)。
也请参见此文档:http://unicode.org/notes/tn12/

回到“ UTF-16有害”,我会说:绝对不是。

害怕代理人的人(认为他们将Unicode转换为可变长度编码)不理解其他(更大的)复杂性,这些复杂性使得字符和Unicode代码点之间的映射非常复杂:结合字符,连字,变体选择器,控制字符等。

只需在此处阅读本系列文章http://www.siao2.com/2009/06/29/9800913.aspx并查看UTF如何-16变成一个简单的问题。

评论


请添加一些示例,其中UNIX世界中UTF-32很常见!

–maxschlepzig
2011年1月13日13:39

不,您不想使用UTF-16进行数据处理。这是一个痛苦的屁股。它具有UTF-8的所有缺点,但没有一个优点。 UTF-8和UTF-32都明显优于以前称为UTF-16夫人的恶意骇客,后者的娘家姓是UCS-2。

–基督
2011年8月11日14:18

我昨天才在Java核心String类的equalsIgnoreCase方法(以及string类中的其他方法)中发现了一个错误,如果Java使用了UTF-8或UTF-32,那将是不可能的。在使用UTF-16的任何代码中,都有数百万个此类沉睡的重磅炸弹,我感到厌烦。 UTF-16是一种恶毒痘,永远困扰着我们的软件,并带有隐患。它显然是有害的,应该弃用并禁止使用。

–基督
2011年8月11日14:53

@tchrist哇,所以这是一种非代理感知的功能(因为它是在没有代理功能的情况下编写的,可悲的是,它的记录方式使得它可能无法适应-它指定.toUpperCase(char))会导致错误的行为?您知道带有过时的代码点映射的UTF-32函数无法更好地处理此问题吗?同样,整个Java API不能很好地处理代理,关于Unicode的更复杂的点也根本无法解决-在以后的版本中,所使用的编码完全无关紧要。

– Voo
2011年8月15日15:32

-1:.NET中的无条件.Substring(1)是一个琐碎的示例,它破坏了对所有非BMP Unicode的支持。所有使用UTF-16的东西都有这个问题。将其视为固定宽度编码太容易了,而且您很少会遇到问题。如果您要支持Unicode,那么它就成为有害的主动编码。

–罗马·斯塔科夫
2012年12月4日15:24



#4 楼

是的,绝对。

为什么?

如果您查看汤姆·克里斯蒂安森(Tom Christiansen)大型语料库上的这些代码点使用情况统计信息,您会发现跨8位BMP代码点的使用量要高出几个级别。 -BMP代码点:

 2663710 U+002013 ‹–›  GC=Pd    EN DASH
 1065594 U+0000A0 ‹ ›  GC=Zs    NO-BREAK SPACE
 1009762 U+0000B1 ‹±›  GC=Sm    PLUS-MINUS SIGN
  784139 U+002212 ‹−›  GC=Sm    MINUS SIGN
  602377 U+002003 ‹ ›  GC=Zs    EM SPACE

 544 U+01D49E ‹𝒞›  GC=Lu    MATHEMATICAL SCRIPT CAPITAL C
 450 U+01D4AF ‹𝒯›  GC=Lu    MATHEMATICAL SCRIPT CAPITAL T
 385 U+01D4AE ‹𝒮›  GC=Lu    MATHEMATICAL SCRIPT CAPITAL S
 292 U+01D49F ‹𝒟›  GC=Lu    MATHEMATICAL SCRIPT CAPITAL D
 285 U+01D4B3 ‹𝒳›  GC=Lu    MATHEMATICAL SCRIPT CAPITAL X


采用TDD格言:“未经测试的代码已损坏代码”,并将其改写为“未执行的代码已损坏代码”,并考虑使用频率程序员必须处理非BMP代码点。

与不处理UTF-16有关的错误比起UTF-8中的等效错误,更容易引起人们的注意。某些编程语言仍然不能保证为您提供UTF-16而不是UCS-2,并且某些所谓的高级编程语言提供对代码单元而不是代码点的访问(甚至C也应允许您访问代码点(如果您使用wchar_t,则不管某些平台可能做什么)。

评论


“与未将UTF-16作为可变宽度编码处理有关的错误比UTF-8中的等效错误更容易被忽视。”这是问题的核心,因此也是正确的答案。

– Sean McMillan
2011年8月19日在13:01

恰恰。如果您对UTF-8的处理感到厌烦,那将立即显而易见。如果您对UTF-8的处理感到厌烦,那么您只会注意到是否输入了不常见的汉字或数学符号。

–机械蜗牛
2012年8月1日在7:26

非常正确,但是,另一方面,如果您应该依靠运气来发现频率较低的情况下的错误,那么单元测试又将如何?

–音乐爱好者
14年6月18日在21:09

@musiphil:那么,您上一次为非BMP字符创建单元测试是什么时候?

– ninjalj
14年6月19日在21:14

详细说明一下我以前的声明:即使使用UTF-8,也不能保证仅在看到一些可用示例之后就涵盖了所有情况。与UTF-16相同:您需要测试您的代码是否适用于非代理和代理。 (甚至有人认为UTF-8至少有四个主要案例,而UTF-16只有两个大案例。)

–音乐爱好者
14年6月19日在22:00

#5 楼

我建议认为UTF-16可能被认为有害,这意味着您需要对Unicode有了更深入的了解。 。您对UTF-16的困扰到底是什么?您是否希望所有内容都以UTF-8编码? UTF-7?还是UCS-4呢?当然,某些应用程序并非旨在处理其中的每个字符代码,但是它们对于在国际边界之间进行通信是必需的,尤其是在当今的全球信息领域。

但是,如果您觉得UTF-16,应该被认为是有害的,因为它令人困惑或可能被不正确地实现(当然可以使用unicode),那么什么字符编码方法将被认为是无害的?标准反映了标准本身的质量?正如其他人随后指出的那样,仅仅是因为应用程序不当使用工具,并不意味着该工具本身就有缺陷。如果是这种情况,我们可能会说诸如“认为var关键字有害”或“认为线程有害”之类的内容。我认为这个问题使标准的质量和性质与许多程序员在正确实施和使用它时遇到的困难混淆了,我觉得这更多是由于他们缺乏对unicode的工作原理而不是unicode本身的理解。

评论


-1:如何解决Artyom的一些反对意见,而不仅仅是光顾他?

– RichieHindle
09-6-26 at 16:12

顺便说一句:当我开始写这篇文章时,我几乎想写“ Unicode的Softeare上的Joes Joel应该被认为是有害的”,因为存在很多错误。例如:utf-8编码最多包含4个字符,而不是6个字符。它也不能区分真正不同的UCS-2和UTF-16 -实际上是引起我所谈论的问题。

– Artyom
09-6-26 at 16:12

另外,应该注意的是,当Joel撰写该文章时,UTF-8标准的WAS为6字节,而不是4字节。RFC3629在撰写本文后的几个月将标准更改为4字节。像互联网上的大多数其他内容一样,从多个来源阅读并了解来源的年代是值得的。该链接并非旨在成为“一切都结束了”,而是一个起点。

–patjbs
09-6-26 at 16:42

我会图片:utf-8或utf-32就是:在几乎所有情况下(包括BMP)可变长度编码或总是固定长度编码。

– Artyom
09年7月12日在6:50

@iconiK:别傻了。 UTF-16绝对不是处理文本的事实上的标准。向我展示一个更适合于文本处理的编程语言,而Perl一直(在十多年来)一直在内部使用带有底层UTF-8表示形式的抽象字符。因此,每个Perl程序都会自动处理所有Unicode,而用户不必不断地摆弄愚蠢的代理人。字符串的长度是其在代码点中的计数,而不是代码单位。其他任何事情都是愚蠢的,使向后兼容成为向后兼容。

–基督
2011年8月11日14:50

#6 楼

Utf-16编码没有问题。但是,将16位单元视为字符的语言可能应该被认为设计错误。具有不总是代表字符的名为“ char”的类型非常令人困惑。由于大多数开发人员都希望char类型表示一个代码点或字符,因此当暴露于BMP以外的字符时,很多代码可能会中断。位代码点将始终代表一个字符。由于组合了字符,实际字符可能包含几个代码点。 Unicode从来都不是小事。

顺便说一句。平台和应用程序可能存在同一类错误,它们期望字符为8位,并由Utf-8提供。

评论


在Java的情况下,如果查看它们的时间轴(java.com/en/javahistory/timeline.jsp),就会发现String的最初发展发生在Unicode是16位的时候(1996年有所变化)。他们不得不增加处理非BMP代码点的能力,从而造成混乱。

–凯西·范·斯通(Kathy Van Stone)
09年6月26日在17:40

@Kathy:不过,这并不是C#的借口。通常,我同意,应该有一个CodePoint类型,一个单一代码点(21位),一个CodeUnit类型,一个单一代码单元(对于UTF-16为16位)和一个Character类型,理想情况下必须支持完整的字素。但这使其在功能上等同于String ...

–乔伊
2010-4-2 13:43

这个答案已经快两年了,但我不禁对此发表评论。 “具有一个不能始终代表字符的名为'char'的类型,这非常令人困惑。”但是人们一直在C等语言中使用它来表示可以存储在单个字节中的整数数据。

– JAB
2011年6月6日15:53

而且我已经看到很多C代码无法正确处理字符编码。

– dan04
11年8月18日在23:06

C#有一个不同的借口:它是为Windows设计的,而Windows是在UCS-2上构建的(即使现在Windows API都不支持UTF-8,这也很令人讨厌)。另外,我认为Microsoft希望Java兼容性(.NET 1.0具有Java兼容性库,但是他们很快放弃了对Java的支持-我猜这是由于Sun对MS提起的诉讼?)

– Qwertie
2012年5月1日0:05

#7 楼

我个人的选择是始终使用UTF-8。这是Linux几乎所有内容的标准。它与许多旧版应用程序向后兼容。与其他UTF格式相比,用于非拉丁字符的额外空间的开销非常小,并且大大节省了拉丁字符的空间。在网络上,拉丁语言占主导地位,我认为它们将在可预见的将来。为了解决原始帖子中的一个主要论点:几乎每个程序员都知道UTF-8有时会包含多字节字符。并不是每个人都正确地处理了这个问题,但是他们通常都知道,这远远超过了UTF-16的说法。但是,当然,您需要选择一种最适合您的应用程序。这就是为什么首先要有多个的原因。

评论


UTF-16对于BMP内部的任何内容都更简单,这就是为什么它被如此广泛地使用。但是我也是UTF-8的粉丝,它在字节顺序方面也没有问题,这对它的优势很有用。

–马尔科姆
09-6-26 at 16:57

从理论上讲,是的。实际上,存在诸如UTF-16BE之类的东西,这意味着大尾数中的UTF-16没有BOM。这不是我整理的,这是ID3v2.4标签允许的实际编码(ID3v2标签很烂,但是不幸的是,被广泛使用)。在这种情况下,您必须在外部定义字节顺序,因为文本本身不包含BOM。 UTF-8始终以一种方式编写,它没有这样的问题。

–马尔科姆
2010-4-2 15:33

不,UTF-16并不简单。很难。它误导并欺骗您以为它是固定宽度的。所有此类代码都已损坏,更重要的是,您要等到为时已晚才注意到。案例要点:昨天我在Java核心库中发现了另一个愚蠢的UTF-16错误,这次是在String.equalsIgnoreCase中,该错误留在了UCS-2的大脑缺陷中,因此在16/17有效的Unicode代码点上失败了。该代码存在多长时间了?没有借口成为越野车。 UTF-16导致纯粹的愚蠢和等待发生的事故。从UTF-16尖叫。

–基督
2011年8月11日14:42

@tchrist必须是一个非常无知的开发人员,才能不知道UTF-16的长度不是固定的。如果您从Wikipedia开始,则将在最上方阅读以下内容:“它产生的可变长度结果是每个代码点一个或两个16位代码单元”。 Unicode常见问题解答也是如此:unicode.org/faq//utf_bom.html#utf16-1。我不知道,如果UTF-16到处都是可变长度的,它怎么会欺骗任何人。至于该方法,它从来都不是为UTF-16设计的,因此不应该被认为是Unicode。

–马尔科姆
11年8月13日在10:30

@tchrist您有统计资料的来源吗?尽管如果缺少优秀的程序员,我认为这很好,因为我们变得更有价值。 :)至于Java API,基于char的部分最终可能会被弃用,但这不能保证它们不会被使用。而且出于兼容性考虑,它们绝对不会被删除。

–马尔科姆
11年8月16日在8:29

#8 楼

嗯,有一种使用固定大小符号的编码。我当然是指UTF-32。但是每个符号4个字节浪费了太多空间,为什么我们要在日常情况下使用它?不能迅速纠正这种情况。 Opera,Windows,Python,Qt-所有这些都在UTF-16广为人知甚至出现之前就出现了。我可以确认,但是,在Opera,Windows资源管理器和记事本中,BMP之外的字符不再存在问题(至少在我的PC上)。但是无论如何,如果程序无法识别代理对,那么它们就不会使用UTF-16。处理此类程序会产生任何问题,但它们与UTF-16本身无关。 BMP之外的字符仅在非常特定的情况和区域才会遇到。根据Unicode官方常见问题解答的说法,“即使在东亚文本中,代理对的发生率也应平均少于所有文本存储的1%”。当然,不应忽略BMP之外的字符,因为否则程序将不符合Unicode,但是大多数程序都不打算用于包含此类字符的文本。这就是为什么如果他们不支持它,那将是令人不快的,但不会造成灾难性后果。如果不存在UTF-16,那么我们将没有一种非常适合非ASCII文本的编码,并且为UCS-2创建的所有软件都必须完全重新设计以保持与Unicode兼容。后者很可能只会减慢Unicode的采用。同样,我们也无法像UTF-8那样相对于ASCII保持与UCS-2中文本的兼容性。

现在,撇开所有遗留问题,反对编码本身的参数是什么?我真的怀疑现在的开发人员不知道UTF-16是可变长度的,它随处可见,写在Wikipedia上。如果有人指出复杂性是一个可能的问题,那么与UTF-8相比,UTF-16的解析难度要小得多。认为仅在UTF-16中确定字符串长度很容易搞乱也是错误的。如果您使用UTF-8或UTF-32,则仍应注意,一个Unicode代码点不一定表示一个字符。除此之外,我认为编码没有任何实质性的内容。

因此,我不认为编码本身就是有害的。 UTF-16是简单性和紧凑性之间的折衷方案,在需要的地方使用所需的东西没有任何危害。在某些情况下,您需要保持与ASCII的兼容性,并且需要UTF-8;在某些情况下,您需要使用Han表意文字,并使用UTF-16节省空间;在某些情况下,您需要通用字符表示形式,长度编码。使用更合适的方法,然后正确执行即可。

评论


马尔科姆(Malcolm)这是一个以眨眼,以盎格鲁为中心的观点。几乎可以与“ ASCII对美国足够好-世界其他地方都适合我们”相提并论。

–乔纳森·莱弗勒(Jonathan Leffler)
09-6-26 at 16:22

实际上,我来自俄罗斯,经常遇到西里尔文(包括我自己的程序),所以我认为我没有以英语为中心的观点。 :)提及ASCII不太合适,因为它不是Unicode且不支持特定字符。 UTF-8,UTF-16,UTF-32支持完全相同的国际字符集,它们仅用于特定领域。这正是我的观点:如果您主要使用英语,请使用UTF-8,如果您主要使用西里尔字母,请使用UTF-16,如果您使用古代语言,请使用UTF-32。非常简单。

–马尔科姆
09-6-26 at 16:36

“不是真的,亚洲脚本(例如日语,中文或阿拉伯语)也属于BMP。BMP本身实际上非常大,而且肯定足够大,足以包括当今使用的所有脚本。” BMP包含0xFFFF字符(65536)。仅中国人就拥有更多。中国标准(GB 18030)不仅如此。 Unicode 5.1已经分配了超过100,000个字符。

– Mihai Nita
09年7月24日在8:11

@Marcolm:“ BMP本身实际上非常大,并且肯定足够大,足以包括当今使用的所有脚本”。至此,Unicode已经分配了大约100K个字符,比BMP可以容纳的更多。 BMP之外有大块汉字。其中一些是GB-18030(强制性中国标准)所必需的。其他(非强制性)日本和韩国标准要求。因此,如果您尝试在这些市场中出售任何产品,那么您将需要BMP以外的支持。

– Mihai Nita
09-09-25 at 21:41

任何使用UTF-16但只能处理窄BMP字符的东西实际上都不在使用UTF-16。这是马车和破碎。 OP的前提是合理的:UTF-16是有害的,因为它会使幼稚的人编写出损坏的代码。您可以处理Unicode文本,也可以不处理。如果不能,那么您将选择一个子集,这与仅ASCII文本处理一样愚蠢。

–基督
2011年8月11日14:46

#9 楼

多年的Windows国际化工作,尤其是在东亚语言中,可能使我败坏了,但是我倾向于使用UTF-16来表示程序内部的字符串,而倾向于使用UTF-8来存储类似明文的文档的网络或文件。但是,通常可以在Windows上更快地处理UTF-16,这就是在Windows中使用UTF-16的主要好处。文本。只有少数几种情况需要考虑代理对(基本上是删除,插入和换行),平均情况主要是直通。与JIS变体之类的早期编码不同,UTF-16将代理对限制在非常窄的范围内,因此检查确实非常快捷,并且可以向前和向后进行。 UTF-8也是如此。但是,还有许多损坏的UTF-8应用程序将代理对错误地编码为两个UTF-8序列。因此,UTF-8也不能保证得到挽救。

自2000年左右以来,IE可以很好地处理代理对,即使它通常将其从UTF-8页面转换为内部UTF-16表示形式也是如此。我相当确定Firefox也可以正确使用,因此我不太在意Opera的功能。

UTF-32(又名UCS4)对大多数应用程序毫无意义,因为它对空间的要求很高,因此几乎是一个入门者。

评论


我对您对UTF-8和代理对的评论不甚满意。代理对只是一个在UTF-16编码中有意义的概念,对吗?直接从UTF-16编码转换为UTF-8编码的代码可能会出现此错误,在这种情况下,问题是错误地读取了UTF-16,而不是编写UTF-8。是对的吗?

–克雷格·麦昆(Craig McQueen)
09年6月27日在23:54

Jason谈论的是故意以这种方式实现UTF-8的软件:创建一个代理对,然后UTF-8分别对每半编码。该编码的正确名称是CESU-8,但Oracle(例如)将其错误表示为UTF-8。 Java为对象序列化采用了类似的方案,但是清楚地记录为“ Modified UTF-8”,并且仅供内部使用。 (现在,如果我们能使人们阅读该文档并停止不当使用DataInputStream#readUTF()和DataOutputStream#writeUTF()...)

–艾伦·摩尔
09年6月28日在14:35

AFAIK,UTF-32仍然是可变长度编码,不等于UCS4,后者是代码点的特定范围。

– Eonil
13年15月15日在21:41

@Eonil,只有我们拥有具有UCS5或更高版本之类的Unicode标准,才会将UTF-32与UCS4区分开。

–JasonTrue
13年15月15日在21:49

@JasonTrue仍然只有巧合的是相等的结果,而不是设计保证的。在32位存储器寻址Y2K,UTF16 / UCS2中也发生了同样的事情。还是我们有平等的保证?如果有的话,我会很乐意使用它。但是我不想编写可能的易碎代码。我正在写一个字符级代码,而缺乏在UTF <->代码点之间进行代码转换的保证方法使我很头疼。

– Eonil
13年15月15日在22:02

#10 楼

UTF-8绝对是必经之路,可能需要在需要高性能随机访问的算法内部使用UTF-32(但忽略组合字符)。 32(以及它们的LE / BE变体)存在字节性问题,因此切勿在外部使用它们。

评论


UTF-8也可以进行恒定时间的随机访问,只需使用代码单位而不是代码点即可。也许您需要真正的随机代码点访问,但是我从未见过用例,并且您也很可能希望使用随机字素集群访问。

–鼠李糖
10年8月6日在7:32

#11 楼

UTF-16?绝对有害。这只是我的事,但是程序中确实有三种可接受的文本编码:


ASCII:当处理不能处理的低级内容(例如微控制器)时< brafford更好的方法
UTF8:存储在文件等固定宽度的介质中
整数代码点(“ CP”?):方便编程的最大整数数组语言和平台(在低分辨率的范围内衰减为ASCII)。在较旧的计算机上应为int32,在具有64位
寻址的任何计算机上应为int64。
显然,与旧代码的接口使用了使旧代码正常工作所需的编码。


评论


@simon buchan,当(如果不是)代码点用完时,U + 10ffff max将会退出窗口。就是说,在p64系统上使用int32来提高速度可能是安全的,因为在您被迫在2050年左右为128位系统重写代码之前,我怀疑它们会超过U + ffffffff。(这就是“使用相对于“最大可用”(可能是int256或bignums之类的东西)。

– David X
2010年6月10日在2:59

@David:Unicode 5.2编码107,361个代码点。有867,169个未使用的代码点。 “何时”只是愚蠢的。 Unicode代码点定义为0到0x10FFFF之间的数字,这是UTF-16所依赖的属性。 (当64位系统可以在其地址空间中容纳整个Internet时,2050年对于128位系统的估计似乎也很低。)

–西蒙·布坎(Simon Buchan)
2010年6月11日下午6:07

@David:您的“何时”是指用完Unicode代码点,而不是在接下来的几个世纪中使用128位开关。与内存不同,字符没有指数增长,因此Unicode联盟特别保证它们绝不会在U + 10FFFF以上分配代码点。这实际上是21位足以满足任何人的情况之一。

–西蒙·布坎(Simon Buchan)
2010年6月13日在2:53

@Simon Buchan:至少直到第一次接触。 :)

– dalle
2010-10-18 17:38

Unicode用来保证在U + FFFF之上也不会有代码点。

– Shannon遣散费
13年10月4日在18:47

#12 楼

Unicode定义的代码点最大为0x10FFFF(1,114,112个代码),所有在多语言环境中运行的处理字符串/文件名等的应用程序都应正确处理。

utf-16:仅涵盖1,112,064个代码。尽管Unicode末尾的内容来自15-16平面(专用区域)。除了打破Utf-16的概念,它在未来无法进一步发展。

Utf-8:理论上涵盖了2,216,757,376个代码。 Unicode代码的当前范围可以由最多4个字节的序列表示。它不存在字节顺序问题,它与ascii“兼容”。Utf-32:理论上涵盖2 ^ 32 = 4,294,967,296个代码。目前,它不是可变长度编码的,可能将来也不会。

这些事实是不言而喻的。我不赞成提倡使用Utf-16。它是可变长度编码的(无法通过索引访问),即使在目前也存在覆盖整个Unicode范围的问题,必须处理字节顺序等。我看不到任何优势,除了它在Windows和其他操作系统中本地使用其他地方。即使在编写多平台代码时,最好原生使用Utf-8并仅以依赖于平台的方式在端点进行转换(如已建议的那样)。当必须通过索引直接访问并且内存不是问题时,应使用Utf-32。

主要问题是许多处理Windows Unicode = Utf-16的程序员甚至都不知道或忽略它是可变长度编码的事实。

它在* nix平台中通常使用的方式非常好,c字符串(char *)解释为Utf-8编码,宽c字符串(wchar_t *)解释为Utf-32。

评论


注意:UTF-16确实涵盖了所有Unicode,因为Unicode联盟决定10FFFF是Unicode的TOP范围,并且已定义UTF-8最大4字节长度,并且从有效代码点范围中明确排除了范围0xD800-0xDFFF,该范围用于创建代理对。因此,任何有效的Unicode文本都可以用这些编码之一来表示。还有关于成长的未来。在任何遥远的将来看来,一百万个代码点似乎还不够。

– Artyom
2011年1月21日15:06

@Kerrek:错误:UCS-2不是有效的Unicode编码。根据定义,所有UTF- *编码都可以表示合法交换的任何Unicode代码点。 UCS-2可以代表的数量远不止于此,还有更多。重复:UCS-2不是有效的Unicode编码,比ASCII还要大。

–基督
2011年8月11日14:33

“我不赞成提倡Utf-8的一般用法。它是可变长度编码的(无法通过索引访问)”

–伊恩·博伊德(Ian Boyd)
2011年8月11日15:35

@Ian Boyd,以随机访问方式访问字符串的单个字符的需求被高估了。它与想要计算字符矩阵的对角线一样普遍,这非常罕见。字符串实际上总是按顺序处理,并且由于假设您位于UTF-8 char N的情况下访问UTF-8 char N + 1是O(1),所以没有问题。几乎不需要随机访问字符串。您是否认为值得使用UTF-32而不是UTF-8的存储空间是您自己的看法,但是对我来说,这完全不是问题。

–基督
2011年8月11日在20:38

@tchrist,如果您将反向迭代包含为“顺序的”,并且将字符串的尾端与已知字符串进行进一步的比较,我将授予您字符串实际上总是按顺序进行处理。两种非常常见的情况是从字符串末尾截断空格并在路径末尾检查文件扩展名。

–安迪·邓特(Andy Dent)
2012年5月13日下午14:16

#13 楼

将其添加到列表中:


呈现的场景很简单(我将在这里展示它比起原来的更加简单!):
1。 WinForms文本框位于窗体上,为空。它的MaxLength设置为20。

2.用户在TextBox中键入文本,或者将文本粘贴到其中。

3.无论您键入或粘贴什么内容在TextBox中,您只能使用20个字符,尽管它会同情地在20个字符之外发出提示音(此处是YMMV
;我更改了音效以达到那种效果!)。

4。然后将一小包文本发送到其他地方,以开始令人兴奋的冒险。

现在,这是一个简单的方案,任何人都可以
在业余时间写下来。我只是使用WinForms用多种编程语言自己编写了代码,因为我很无聊,并且以前从未尝试过。并使用多种实际语言的文本
,因为我采用这种方式接线,并且键盘布局要比整个怪异世界中的任何人都要多。

我什至将
命名为Magic Carpet Ride,以帮助缓解这种无聊感。

这没有用,因为它值得。

因此,我改为在我的“魔毯骑行”表单中输入以下20个
字符:

嗯。

最后一个字符是U + 20000,这是Unicode的第一个扩展B
表意符号(又名U + d840 U + dc00,对于他的亲密朋友来说,他并不感到羞耻...)。



现在我们有了一个球类游戏。

因为TextBox.MaxLength谈论
关于

获取或设置可以手动输入到文本框中的最大字符数。

真正的意思是

获取或设置
可以在文本框中手动输入的最大UTF-16 LE代码单元数,
将无情地截断生活
从试图用
玩可爱游戏的任何字符串中剔除掉语言字符的概念是,只有如此痴迷的人会感到反感(天才,他需要进一步努力!)。

我将尝试了解如何对文档进行更新。 ...
经常记住我的UCS-2至UTF-16系列的读者会注意到我的
不满意,它带有TextBox.MaxLength的简单概念以及它应该如何处理在这种情况下,其苛刻的行为
创建了一个非法序列,.NET
框架的其他部分可能会抛出一个非法序列。 :无法
将索引0处的Unicode字符\ uD850转换为指定的代码
页面。*

如果将此字符串传递到.Net的其他地方,则为例外
Framew ork(就像我的同事Dan Thompson所做的那样)。

现在好了,
也许从许多UCS-2到UTF-16的完整系列都无法实现。
但是,期望TextBox.Text是不合理的不会产生不会导致.Net Framework的另一部分抛出

System.String?我的意思是,这并不是像控件上的某些
事件形式会告诉您即将出现的截断,您可以在其中轻松地添加更智能的验证-验证<控件本身并不介意这样做。我什至可以说,
如果您可以分类导致意外的异常,从而导致应用程序
终止,则该朋克控件将破坏甚至可能导致安全问题的安全契约。拒绝服务。为什么
任何WinForms进程,方法,算法或技术
都将产生无效结果?


来源:Michael S. Kaplan MSDN博客

评论


谢谢,很好的链接!我已将其添加到问题的问题列表中。

– Artyom
2010-12-21在6:28

#14 楼

我不一定要说UTF-16是有害的。它虽然不优雅,但其目的是与UCS-2向后兼容,就像GB18030与GB2312和UTF-8与ASCII一样。

但是对Unicode的结构进行了根本性的改变在中间阶段,在Microsoft和Sun建立了围绕16位字符的巨大API之后,这是有害的。未能传播对变更的认识更加有害。

评论


UTF-8是ASCII的超集,但UTF-16不是UCS-2的超集。尽管几乎是一个超集,但将UCS-2正确编码为UTF-8会导致可憎的现象,即CESU-8。 UCS-2没有替代品,只有普通的代码点,因此必须照此翻译。 UTF-16的真正优势在于,与完整重写UTF-8相比,升级UCS-2代码库要容易得多。好笑吧?

–鼠李糖
10年8月6日在7:28

当然,从技术上讲UTF-16并不是UCS-2的超集,但是什么时候U + D800到U + DFFF可以用于除UTF-16代理人之外的任何东西?

– dan04
2010年8月17日在18:51

没关系除了盲目地通过字节流之外,任何其他处理都需要您解码代理对,如果将其视为UCS-2,则无法执行。

–鼠李糖
2010年8月29日在13:02

#15 楼

UTF-16是处理和空间之间的最佳折衷方案,这就是为什么大多数主要平台(Win32,Java,.NET)都将UTF-16用于内部字符串表示。

评论


-1,因为UTF-8可能会更小或没有明显的不同。对于某些亚洲文字而言,UTF-8每字形为3个字节,而UTF-16只有2个字节,但这可以通过UTF-8对于ASCII仅为1个字节来平衡(即使在亚洲语言中,产品名称,命令等也经常出现这种情况)东西)。此外,在所述语言中,字形传达的信息多于拉丁字符,因此有理由占用更多空间。

–Tronic
2010-3-18的2:47

我不会将两种选择的最坏方面结合起来是一个很好的妥协。

–Tronic
10 Mar 23 '10在15:36

这并不比UTF-8容易。它也是可变长度的。

–luiscubal
2010-3-25在17:50

除了关于UTF-16的好处的争论之外:您提到的并不是Windows,Java或.NET使用UTF-16的原因。 Windows和Java可以追溯到Unicode是16位编码的时代。当时,UCS-2是一个合理的选择。当Unicode成为21位编码时,迁移到UTF-16是现有平台的最佳选择。这与易于处理或空间妥协无关。这只是遗留问题。

–乔伊
2010-4-2 14:13

.NET继承了Windows的传统。

–乔伊
10年4月2日在16:19

#16 楼

我从来不了解UTF-16的要点。如果您想要最节省空间的表示形式,请使用UTF-8。如果希望能够将文本视为固定长度,请使用UTF-32。如果您都不想要,请使用UTF-16。更糟糕的是,由于UTF-16中的所有常见(基本多语言平面)字符都位于单个代码点中,因此假设UTF-16是固定长度的错误将很难发现,而如果您尝试这样做,使用UTF-8时,一旦您尝试进行国际化,您的代码就会快速响亮。

#17 楼

由于无法发表评论,因此将其发布为答案,因为似乎无法以其他方式联系utf8everywhere.org的作者。可惜我没有自动获得评论特权,因为我在其他stackexchanges上有足够的声誉。
这是对意见的评论:是的,应该将UTF-16视为有害答案。
一项更正:
为防止将UTF-8 char*意外传递到Windows API API函数的ANSI字符串版本中,应定义UNICODE而不是_UNICODE_UNICODE映射类似_tcslenwcslen的函数,而不是MessageBoxMessageBoxW的函数。而是由UNICODE定义处理后者。
为证明起见,此消息来自MS Visual Studio 2005的WinUser.h标头:
一个建议:
也许指南应该包含一个显式使用数据结构的宽字符串版本的示例,以减少丢失/忘记它的难度。在使用函数的宽字符串版本的基础上再使用宽字符串版本的数据结构,可以减少意外调用此类函数的ANSI字符串版本的可能性。
示例示例:
#ifdef UNICODE
#define MessageBox  MessageBoxW
#else
#define MessageBox  MessageBoxA
#endif // !UNICODE


评论


同意;谢谢!我们将更新文档。该文档仍需要更多开发并添加有关数据库的信息。我们很高兴收到措辞的贡献。

–帕维尔·拉齐维洛夫斯基(Pavel Radzivilovsky)
14年2月14日在12:41

@PavelRadzivilovsky _UNICODE仍然存在:(

–cubuspl42
2014年4月18日在12:19

感谢您的提醒。 cubus,Jelle,您想要我们SVN的用户吗?

–帕维尔·拉齐维洛夫斯基(Pavel Radzivilovsky)
2014年4月25日在13:15

@Pavel当然,会很感激!

–Jelle Geerts
2014-4-25 13:45

@JelleGeerts:对于这个延迟,我深表歉意。您可以随时通过我们的电子邮件(从宣言链接)或Facebook与我们联系。我们很容易找到。尽管我相信我们已解决了您在此处提出的问题(并且我在此表示感谢),但整个UTF-8与UTF-16的辩论仍然有意义。如果您有更多贡献,请随时通过这些私人渠道与我们联系。

– ybungalobill
15年6月24日在19:03

#18 楼

有人说UCS4和UTF-32是相同的。不,但是我知道你的意思。不过,其中之一是另一种的编码。我希望他们从一开始就考虑指定字节序,这样我们就不会在这里进行字节序之争。他们难道没有看到那件事吗?至少所有地方的UTF-8都是一样的(除非有人遵循原始的6字节规范)。

如果使用UTF-16,则必须包括对多字节字符的处理。您无法通过将2N索引到字节数组中来进入第N个字符。您必须步行,或具有字符索引。否则,您可能会写一个错误。

当前的C ++规范草案指出UTF-32和UTF-16可以具有little-endian,big-endian和未指定的变体。真?如果Unicode规定每个人都必须从一开始就做小尾数法,那么这将变得更加简单。 (使用big-endian也会很好。)相反,有些人以一种方式实现了它,而另一些则以另一种方式实现了,现在我们陷入了无聊的愚蠢之中。有时候成为一名软件工程师会很尴尬。

评论


未指定的字节序应该包含BOM作为第一个字符,用于确定应以哪种方式读取字符串。如今,UCS-4和UTF-32确实是相同的,即以32位整数存储的介于0到0x10FFFF之间的UCS数值。

–Tronic
2010-10-20 23:34

@Tronic:从技术上讲,这是不正确的。尽管UCS-4可以存储任何32位整数,但是UTF-32禁止存储对于互换而言是非法的非字符代码点,例如0xFFFF,0xFFFE和所有替代项。 UTF是一种传输编码,而不是内部编码。

–基督
2011年8月11日14:30

只要不同的处理器继续使用不同的字节顺序,字节序问题就不可避免。但是,如果对UTF-16的文件存储有“首选”字节顺序,则可能会很好。

– Qwertie
2012年5月1日0:16

即使UTF-32对于代码点是固定宽度的,对于字符也不是固定宽度的。 (听说过“组合字符”吗?)因此,不能简单地通过将4N索引到字节数组中来进入第N个字符。

–音乐爱好者
2014年6月19日在5:05



#19 楼

如果开发人员足够小心,我认为这没有什么害处。
如果他们也很了解,他们应该接受这种折衷。

作为一名日本软件开发人员,我发现UCS-2足够大,并且限制空间显然简化了逻辑并减少了运行时内存,因此在UCS-2限制下使用utf-16就足够了。

有些文件系统或其他应用程序假定代码点和字节成比例,因此可以确保原始代码点号适合某些固定大小的存储。

一个示例是NTFS和VFAT,它们将UCS-2指定为其文件名存储编码。

如果这些示例确实想要扩展以支持UCS-4,无论如何我都同意使用utf-8,但是固定长度具有以下优点: />可以按长度保证大小(数据大小和代码点长度成比例)
可以使用编码号进行哈希查找
非压缩数据的大小合理(与utf-32 / UCS-4相比) )

将来,即使在任何嵌入式设备中,内存/处理能力仍然很便宜,我们可能会接受该设备因缓存丢失或页面错误以及内存使用量过慢而有点慢,但这不会发生我想在不久的将来...

评论


对于那些阅读此评论的人来说,值得注意的是,UCS-2与UTF-16并不相同。请查找差异以了解。

–mikebabcock
2012-12-19 19:39



#20 楼


“应该认为最流行的编码之一UTF-16是有害的吗?”


很有可能,但是替代方法不一定被认为是更好的方法。

基本问题是关于字形,字符,代码点和字节序列有许多不同的概念。即使在归一化库的帮助下,它们之间的映射也不是简单的。 (例如,某些欧洲语言的字符是使用基于拉丁语的脚本编写的,而不是使用单个Unicode代码点编写的。这只是复杂性的简单体现!)这意味着使所有内容正确无比是非常令人惊讶的难;可以预料到会有奇怪的错误(而不是在这里抱怨,而是告诉相关软件的维护者)。

唯一的方法可以认为UTF-16有害而不是也就是说,UTF-8的编码方式不同于BMP(作为一对代理),它具有不同的编码方式。如果代码希望按代码点进行访问或迭代,则意味着它需要意识到它们之间的区别。 OTOH确实意味着,假设“字符”的现有代码主体可以始终装入两个字节的数量中(一个相当普遍的假设,如果错误的话,假设)至少可以继续工作而无需重新构建所有代码。换句话说,至少您会看到那些处理不正确的字符!每个人都应该使用8位编码,除非我看到(过去20年来)会导致以下问题:各种ISO 8859编码,用于西里尔字母的整个编码集以及EBCDIC套件都令人震惊,而且…嗯,Unicode的所有缺点都胜过了。如果不是在不同国家的误解之间做出如此令人讨厌的妥协。

评论


知道我们的运气,几年后,我们会发现自己在UTF-16中耗尽了空间。嗯

–研究员
2011年8月21日在15:57

根本问题是文本很难看。以数字方式表示该信息的方法绝不复杂。这是相同的原因,日期很难,日历难,时间难,人名难,邮政地址难:每当数字机器与人类文化构造相交时,复杂性就会爆发。这是生活中的事实。人类无法发挥数字逻辑的作用。

–亚里斯多德·帕加尔齐斯(Aristotle Pagaltzis)
2012年5月7日,1:16