我该怎么用?UTF8还是UTF16?

WeG*_*ars 17 delphi utf-8 utf-16

我必须在国际上分发我的应用程序.

假设我有一个用户输入一些文本的控件(如备忘录).用户可以是日语,俄语,加拿大等.我想将字符串保存为磁盘作为TXT文件供以后使用.我将使用MY OWN函数来编写文本而不是TMemo.SaveToFile().

我如何将字符串保存到磁盘?采用UTF8或UTF16格式?

Com*_*sMS 30

它们之间的主要区别在于UTF8向后兼容ASCII.只要您只使用前128个字符,非Unicode识别的应用程序仍然可以处理数据(这可能是优势或劣势,具体取决于您的方案).特别是,当切换到UTF16时,每个 API函数都需要针对16位字符串进行调整,而使用UTF8时,如果不进行任何字符串处理,通常可以保持旧的API函数不变.UTF8也不依赖于字节序,而UTF16则不依赖于字符串I/O.

一个常见的误解是UTF16更容易处理,因为每个字符总是占用两个字节.不幸的是,这不是真的.UTF16是一种可变长度编码,其中一个字符可能占用2或4个字节.因此,与UTF8相关的关于可变长度问题的任何困难也适用于UTF16.

最后,存储大小:关于UTF16的另一个常见误区是,对于大多数外语来说,它比UTF8更具存储效率.UTF8 为所有欧洲语言占用较少的存储空间,每个字符可以编码一个或两个字节.非BMP字符在UTF8和UTF16中占用4个字节.UTF16占用较少存储空间的唯一情况是文本主要由U + 0800到U + FFFF范围内的字符组成,其中存储了中文,日文和印地文的字符.

James McNellis在BoostCon 2014上发表了精彩的演讲,详细讨论了不同编码之间的各种权衡.虽然谈话的标题是C++中的Unicode,但整个上半部分实际上与语言无关.一个完整的谈话录像可在Boostcon的YouTube频道,而幻灯片可以在github上找到.


Mar*_*ema 27

取决于您的数据的语言.

如果您的数据主要使用西方语言并且您希望减少所需的存储量,请使用UTF-8,因为这些语言大约需要UTF-16的一半存储空间.您将在读取数据时支付罚金,因为它将/需要转换为UTF-16,这是Windows默认值并由Delphi(Unicode)字符串使用.

如果您的数据主要使用非西方语言,则UTF-8可以占用比UTF-16更多的存储空间,因为对于某些人来说,每个字符最多可能占用6 字节.(见@KennyTM的评论)

基本上:使用用户数据的代表性样本进行一些测试,并查看哪些在存储要求和加载时间方面表现更好.我们有一些惊喜,UTF-16比我们想象的要慢.由于磁盘访问,因为UTF-16中的数据量更大,因此无需从UTF-8转换为UTF-16的性能增益丢失.

  • UTF-8最多可以占用4个字节.UTF-16中的代理对不应单独转换为UTF-8. (7认同)
  • 实际上,与额外的I/O开销相比,UT8到UTF16的转换开销几乎总是可以忽略不计,即使数据存储在SSD上也是如此. (3认同)

Arn*_*hez 10

首先,请注意Windows下的标准编码是UCS2(直到Windows 2000)或UTF-16(从XP开始),Delphi本机" string"类型使用自Delphi 2009(string=UnicodeString char=WideChar)以来的相同本机格式.

在所有情况下,假设1 WideChar== 1个Unicode字符是不安全的- 这是代理问题.

关于UTF-8或UTF-16的选择,它取决于存储本身:

  • 如果您的文件是纯文本文件(包括XML),您可以使用UTF-8或UTF-16 - 但是您必须在文件的开头使用BOM,否则应用程序(如记事本)可能会在打开时混淆 - 对于XML,这由您的库处理(如果不是,则更改为另一个库);
  • 如果您确定您的内容大多是7位ASCII,请使用UTF-8和相关的BOM;
  • 如果您的文件是某种数据库或自定义二进制格式,当然最好的格式是UTF-16/UCS2,即默认的Delphi 2009+ string布局,当然还有默认的数据库API布局;
  • 某些文件格式需要或更喜欢UTF-8(如JSON甚至SQLite3),即使UTF-8文件对于亚洲字符大于UTF-16也是如此.

例如,我们使用UTF-8作为我们的Client-Server框架,因为我们使用JSON作为交换格式(需要UTF-8),并且因为SQlite3喜欢UTF-8.当然,我们必须编写一些专用的函数和类,以避免转换为/从string(string=UnicodeString自Delphi 2009以来类型的速度很慢,并且string=AnsiString在Delphi 2009之前使用类型时可能会丢失一些数据.请参阅此文章本单元) .最简单的方法是依赖string=UnicodeString类型,使用直接处理UTF-16编码的RTL函数,并避免转换.不要忘记你以前的问题.

如果磁盘空间和读/写速度有问题,请考虑使用压缩而不是更改编码.有实时压缩(比ZIP快),如LZO或我们的SynLZ.

  • Windows 在 Windows 2000 中切换到 UTF-16,而不是 XP。 (2认同)
  • Unicode 标准建议不要使用 [UTF-8] (http://en.wikipedia.org/wiki/UTF-8) 的 BOM (2认同)