我必须在国际上发布我的应用。
假设我有一个控件(如备忘录),用户输入一些文字。用户可以是日语,俄语,加拿大等。 我想将字符串保存为磁盘作为TXT文件供以后使用。我将使用MY OWN函数来编写文本而不是TMemo.SaveToFile()。
如何将字符串保存到磁盘?采用UTF8或UTF16格式?
答案 0 :(得分:30)
它们之间的主要区别在于UTF8向后兼容ASCII。只要您只使用前128个字符,非Unicode识别的应用程序仍然可以处理数据(这可能是优势或劣势,具体取决于您的方案)。特别是,当切换到UTF16 时,每个 API函数需要针对16位字符串进行调整,而使用UTF8时,如果不执行任何字符串处理,通常可以保持旧的API函数不受影响。 UTF8也不依赖于字节序,而UTF16则不依赖于字符串I / O.
一个常见的误解是UTF16更容易处理,因为每个字符总是占用两个字节。不幸的是,这不是真的。 UTF16是一种可变长度编码,其中一个字符可能占用2或4个字节。因此,与UTF8相关的关于可变长度问题的任何困难也适用于UTF16。
最后,存储大小:关于UTF16的另一个常见误区是,对于大多数外语来说,它比UTF8更具存储效率。 UTF8为所有欧洲语言提供 less 存储,每个字符可以编码一个或两个字节。非BMP字符在UTF8和UTF16中占用4个字节。 UTF16占用较少存储空间的唯一情况是文本主要由U + 0800到U + FFFF范围内的字符组成,其中存储了中文,日文和印地文的字符。
James McNellis在BoostCon 2014上发表了精彩演讲,详细讨论了不同编码之间的各种权衡。即使谈话的标题是 Unicode in C ++ ,整个上半部分实际上与语言无关。一个video recording of the full talk is available at Boostcon's Youtube channel,而slides can be found on github。
答案 1 :(得分:27)
取决于您的数据的语言。
如果您的数据主要使用西方语言并且您希望减少所需的存储量,请使用UTF-8,因为这些语言大约需要UTF-16的一半存储空间。您将在读取数据时支付罚金,因为它将/需要转换为UTF-16,这是Windows默认值并由Delphi(Unicode)字符串使用。
如果您的数据主要是非西方语言,UTF-8可以占用比UTF-16更多的存储空间,因为每个字符可能需要 6 4 字节对于一些。 (见@KennyTM的评论)
基本上:使用用户数据的代表性样本进行一些测试,并查看哪些在存储要求和加载时间方面表现更好。我们有一些惊喜,UTF-16比我们想象的要慢。由于磁盘访问,因为UTF-16中的数据量更大,因此无需从UTF-8转换为UTF-16的性能提升已丢失。
答案 2 :(得分:10)
首先,请注意Windows下的标准编码是UCS2(直到Windows 2000)或UTF-16(自XP以来),Delphi本机“string
”类型使用相同的本机格式,因为Delphi 2009年(string=UnicodeString char=WideChar
)。
在所有情况下,假设1 WideChar
== 1个Unicode字符是不安全的 - 这是surrogate问题。
关于UTF-8或UTF-16选择,它取决于存储本身:
例如,我们在客户端 - 服务器框架中使用了UTF-8,因为我们使用JSON作为交换格式(需要UTF-8),并且因为 SQlite3 喜欢UTF-8。当然,我们必须编写一些专用的函数和类,以避免转换为string
(自{Delphi 2009以来string
类型的转换速度很慢,并且在与{{{{}}一起使用时可能会丢失一些数据1}}在Delphi 2009之前输入。请参阅this post和this unit)。最简单的方法是依赖string=UnicodeString
类型,使用直接处理UTF-16编码的RTL函数,并避免转换。不要忘记your previous question。
如果磁盘空间和读/写速度有问题,请考虑使用压缩而不是更改编码。有实时压缩(比ZIP快),如LZO或我们的SynLZ。