C++字符串:UTF-8还是16位编码?

12

我还在考虑是否应该使用 UTF-8 字符串(以 std::string 的形式实现,必要时附加 UTF-8 特定的函数)或某种 16 位字符串(以 std::wstring 实现)来完成我的(家庭)项目。这个项目是一种编程语言和环境(类似于 VB,它是两者的结合体)。

有一些愿望/限制:

  • 如果能在硬件有限的计算机上运行,比如内存有限的计算机,那就太好了。
  • 我希望代码能在 Windows、Mac 和(如果资源允许)Linux 上运行。
  • 我将使用 wxWidgets 作为 GUI 层,但我希望与该工具包交互的代码被限制在代码库的一个角落(我将有非 GUI 可执行文件)。
  • 我希望在处理用户可见文本和应用程序数据时避免使用两种不同的字符串。

目前,我正在使用 std::string,并打算仅在必要时使用 UTF-8 操作函数。这需要更少的内存,而且似乎是许多应用程序正在走向的方向。

如果你推荐使用 16 位编码,那么应该选用哪种:UTF-16UCS-2?还是其他的编码方式?


1
Micro ATX并不意味着内存有限。我家里的电脑是在一个(Micro-ATX)ASUS M2A-VM上运行Crysis非常好。 - davidtbernal
我已经编辑了问题,删除了错误。 - Delan Azabani
8个回答

26

UTF-16是一种可变长度的字符编码(Unicode代码点超过2^16),因此无法执行O(1)字符串索引操作。如果您需要经常进行这种操作,那么使用UTF-8并不会提高速度。另一方面,如果您的文本包含大量256-65535范围内的码点,则使用UTF-16可以在文件大小上获得实质性的改进。UCS-2是UTF-16的变体,它是定长的,但代价是禁止任何大于2^16的码点。

如果没有更多关于您需求的了解,我个人会选择UTF-8。出于其他人已经列出的所有原因,它是最易于处理的。


6

老实说,我从来没有找到使用除UTF-8之外的任何东西的理由。


5

4

我实际上写了一个被广泛使用的应用程序(500万+用户),因此每使用一千字节就会增加,这是真的。尽管如此,我仍然坚持使用wxString。我已经配置它派生自std::wstring,这样我就可以将它们传递给需要一个wstring const &的函数。

请注意,在Mac上,std::wstring是本地Unicode(对于U+10000以上的字符不需要UTF-16),因此它使用4个字节/wchar_t。 这样做的最大优点是i++总是能得到下一个字符。在Win32上,这只有99.9%的情况是正确的。作为一名程序员,你会明白99.9%有多少不确定性。

但是,如果你还没有被说服,请编写一个函数来将std :: string [UTF-8]和std :: wstring转换为大写。这两个函数会告诉您哪种方式是疯狂的。

您的磁盘格式是另一回事。为了可移植性,它应该是UTF-8。在UTF-8中没有字节序问题,也没有宽度(2/4)的讨论。这可能是为什么许多程序似乎使用UTF-8的原因。

稍微离题一点,请了解Unicode字符串比较和规范化。否则,您将会遇到与.NET相同的错误,即具有仅在规范化(不可见)方面有所不同的两个变量föö和föö。


2
请注意,在Mac上使用UTF32会占用大量内存。您提到的0.1%情况意味着在Mac上的任何wstring都将比Windows上的相同字符串的UTF16大两倍(我甚至不会提及Linux的char)。这确实是Linux使用UTF-8 char和Windows使用UTF-16 wchar_t的原因之一。 - paercebal

2
我建议在任何数据操作和UI方面都使用UTF-16。Mac OS X和Win32 API、wxWidgets、Qt、ICU、Xerces等都使用UTF-16。对于数据交换和存储,UTF-8可能更好。请参见http://unicode.org/notes/tn12/
但无论您选择什么,我绝对不建议使用带有UTF-8的std::string“只有在必要时”。全部使用UTF-16或UTF-8,但不要混合使用,这样会引发问题。

1
我的团队的Mac程序员说wchar_t是32位的。而且我们的代码库中肯定有很多代码会出问题。 - MSalters
只是为了澄清:我所说的“仅在必要时使用utf-8”实际上是指,只有当我真正需要处理字符时才会使用一些utf-8操作函数 - 但所有字符串都将始终为utf-8。 - Carl Seleborg
我想要GUI和数据领域之间有明确的分离。后者将完全关注交换和存储,因此我不介意GUI层从utf-8编码的std::string对象转换为utf-16 wxStrings。 - Carl Seleborg
3
您可能希望阅读关于UTF-16的这个问题:http://stackoverflow.com/questions/1049947/should-utf-16-be-considered-harmful - davidtbernal

2

MicroATX是一种标准的PC主板格式,最多可容纳4-8 GB的RAM。如果你说的是picoATX,可能只能限制在1-2 GB RAM。即使如此,这对于开发环境来说已经足够了。出于上述原因,我仍然建议使用UTF-8,但内存不应成为您担心的问题。


@Peter Mortensen:啊,谢谢。我不知道那个功能。 - Patrick Niedzielski

1
根据我所了解的,除非你内存不足,否则最好使用16位编码。它可以用一个字符表示几乎所有的活语言。
我还建议看看ICU。如果你不会使用字符串的某些STL特性,那么使用ICU字符串类型可能更好。

实际上,UTF-16 可以用两个字节来表示大多数现代语言字符;请查看代码点图表,了解 U+10000 以上的代码点;它们都是古希腊或罗马符号。 - Ben Straub

0
你考虑过使用wxStrings吗?如果我没记错的话,它们可以执行utf-8 <-> Unicode转换,当你需要在UI中传递字符串时,会使其更加容易。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接