你如何编写对UTF-8安全的代码?

时间:2008-09-25 16:30:20

标签: c++ unicode utf-8 globalization

我们有一组为ASCII字符集开发的应用程序。现在,我们正试图在冰岛安装它,并且遇到了冰岛角色搞砸的问题。

我们正在解决我们的问题,但我想知道:是否有一个很好的“指南”用于编写专为8位字符设计的C ++代码,并且在为其提供UTF-8数据时可以正常工作?

我不能指望每个人都阅读整个Unicode标准,但如果有更易于理解的内容,我想与团队分享,以便我们不再遇到这些问题。

此时重写所有要使用wchar_t或其他字符串表示的应用程序是不可行的。我还要注意,这些应用程序通过网络与使用8位字符的服务器和设备进行通信,因此即使我们在内部执行Unicode,我们仍然会遇到边界转换问题。在大多数情况下,这些应用程序只传递数据;他们不会以任何方式“处理”文本,除了将文本从一个地方复制到另一个地方。

使用的操作系统是Windows和Linux。我们使用std :: string和普通的C字符串。 (并且不要让我为任何设计决定辩护。我只是想帮助解决这个问题。)


以下列出了已建议的内容:

8 个答案:

答案 0 :(得分:10)

大部分都是8位清洁。但是,您必须注意,任何非ASCII字符都会分割多个字节,因此如果要显示换行符或截断文本,则必须考虑这一点。

UTF-8的优势在于您始终能够确定多字节字符的位置:如果第7位置1且第6位复位(字节为0x80-0xBF),则这是一个尾随字节,而如果是第7位设置为6,复位为5(0xC0-0xDF),它是一个带有一个尾随字节的前导字节;如果设置了7,6和5并且复位了4(0xE0-0xEF),则它是带有两个尾随字节的前导字节,依此类推。设置在最高有效位的连续位数是组成字符的总字节数。那就是:

110x xxxx =双字节字符
1110 xxxx =三字节字符
1111 0xxx =四字节字符

冰岛语字母表全部包含在ISO 8859-1中,因此包含在Windows-1252中。如果这是一个控制台模式应用程序,请注意控制台使用IBM代码页,因此(取决于系统区域设置)它可能显示在437,850或861中。 Windows没有UTF-8的原生显示支持;您必须转换为UTF-16并使用Unicode API。

如果是控制台模式应用程序,则调用SetConsoleCP和SetConsoleOutputCP(指定代码页1252)将有助于解决您的问题。不幸的是,选择的控制台字体必须是支持代码页的字体,我看不到设置字体的方法。标准位图字体仅支持系统默认的OEM代码页。

答案 1 :(得分:3)

这看起来像一本全面的快速指南:
http://www.cl.cam.ac.uk/~mgk25/unicode.html

答案 2 :(得分:1)

请注意,完整的unicode不适合16位字符;所以要么使用32位字符,要么使用可变宽度编码(UTF-8是最受欢迎的)。

答案 3 :(得分:1)

UTF-8的设计完全考虑到了您的问题。我要小心的一点是,ASCII实际上是一个7位编码,所以如果你的基础设施的任何部分使用第8位用于其他目的,那可能会很棘手。

答案 4 :(得分:1)

您可能想查看icu。它们可能具有可以使UTF-8字符串更容易使用的功能。

答案 5 :(得分:0)

Icelandic使用ISO Latin 1,因此8位应该足够了。我们需要更多细节来弄清楚发生了什么。

答案 6 :(得分:0)

冰岛语,如法语,德语和西欧的大多数其他语言,可以使用8位字符集(Windows上的CP1252,* x上的ISO 8859-1也称为Latin1)来支持。这是Unicode发明之前的标准方法,并且仍然很常见。正如你所说,你有一个约束,你不能重写你的应用程序使用wchar,你不需要。

你不应该对UTF-8造成问题感到惊讶; UTF-8将非ASCII字符(例如带有重音的拉丁字符,刺,eth等)编码为两个字符。

唯一可以给出的一般建议很简单(理论上): (1)决定你要支持的字符集(Unicode,Latin1,CP1252,...) (2)如果您提供以其他方式编码的数据(例如UTF-8),则将其转码为系统边界处的标准(例如CP1252) (3)如果你需要提供以其他方式编码的数据,......

答案 7 :(得分:-1)

您可能希望使用宽字符(wchar_t而不是char和std :: wstring而不是std :: string)。这不会自动解决100%的问题,但这是第一步。

还使用支持Unicode的字符串函数(请参阅文档)。如果有东西操纵宽字符或字符串,它通常会意识到它们很宽。

相关问题