C++ UNICODE、UTF-8和Windows mess
C++ UNICODE、UTF-8和Windows mess,c++,c,windows,unicode,utf-8,C++,C,Windows,Unicode,Utf 8,我正在尝试在Windows中实现文本支持,并打算以后也转向Linux平台。以统一的方式支持国际语言是很理想的,但考虑到这两个平台,这似乎并不容易实现。我花了相当多的时间阅读UNICODE、UTF-8(和其他编码)、widechars等,以下是我到目前为止理解的内容:
UNICODE作为标准,描述了可映射的字符集及其出现的顺序。我将其称为“what”:UNICODE指定可用的内容
UTF-8(和其他编码)指定如何:如何以二进制格式表示每个字符
现在,在windows上,他们最初选择了UCS-2编码
我正在尝试在Windows中实现文本支持,并打算以后也转向Linux平台。以统一的方式支持国际语言是很理想的,但考虑到这两个平台,这似乎并不容易实现。我花了相当多的时间阅读UNICODE、UTF-8(和其他编码)、widechars等,以下是我到目前为止理解的内容:
UNICODE作为标准,描述了可映射的字符集及其出现的顺序。我将其称为“what”:UNICODE指定可用的内容
UTF-8(和其他编码)指定如何:如何以二进制格式表示每个字符
现在,在windows上,他们最初选择了UCS-2编码,但这不符合要求,所以UTF-16就是他们所拥有的,必要时也是多字符的
这就是德莱玛:
Windows内部仅支持UTF-16,因此,如果您想支持国际字符,则必须将其转换为widechar版本,以便相应地使用操作系统调用。似乎不支持使用多字节UTF-8字符串调用CreateFileA()之类的东西,并使其看起来正常。这是正确的吗
在C语言中,有一些支持多字节的函数(_mbscat、_mbscpy等),但是在windows上,这些函数的字符类型定义为无符号字符*。鉴于_mbs系列函数不是一个完整的集合(例如,没有将多字节字符串转换为长字符串的_mbstol),您不得不使用一些char*版本的运行时函数,这会导致编译器问题,因为这些函数之间的有符号/无符号类型不同。有人用过吗?你只是做了一大堆的铸造来避免错误吗
在C++中,STD::string有迭代器,但是这些是基于CARYL类型,而不是基于代码点。因此,如果我在std::string::iterator上执行一个+,我将得到下一个字符类型,而不是下一个代码点。类似地,如果调用std::string::operator[],则会得到对char_类型的引用,该类型很可能不是完整的代码点。那么,如何按代码点迭代std::string呢?(C具有_mbsinc()函数)
Windows内部仅支持UTF-16,因此,如果您想支持国际字符,则必须将其转换为widechar版本,以便相应地使用操作系统调用。似乎不支持使用多字节UTF-8字符串调用CreateFileA()之类的东西,并使其看起来正常。这是正确的吗
是的,没错。*A
函数变量根据当前活动的代码页(在美国和西欧的大多数计算机上是Windows-1252,但通常可以是其他代码页)解释字符串参数,并将其转换为UTF-16。有一个UTF-8代码页,但是没有一种方法可以通过编程设置活动代码页(可以获取活动代码页,但没有相应的SetACP
)
在C语言中,有一些支持多字节的函数(_mbscat、_mbscpy等),但是在windows上,这些函数的字符类型定义为无符号字符*。鉴于_mbs系列函数不是一个完整的集合(例如,没有将多字节字符串转换为长字符串的_mbstol),您不得不使用一些char*版本的运行时函数,这会导致编译器问题,因为这些函数之间的有符号/无符号类型不同。有人用过吗?你只是做了一大堆的铸造来避免错误吗
根据我的经验,mbs*
函数族几乎从未使用过。除了mbstowcs
、mbsrtowcs
和mbsinit
,这些功能不是标准的C
在C++中,STD::string有迭代器,但是这些是基于CARYL类型,而不是基于代码点。因此,如果我在std::string::iterator上执行一个+,我将得到下一个字符类型,而不是下一个代码点。类似地,如果调用std::string::operator[],则会得到对char_类型的引用,该类型很可能不是完整的代码点。那么,如何按代码点迭代std::string呢?(C具有_mbsinc()函数)
我认为这是解码多字节字符串的单个代码点的最佳选择
总的来说,我认为跨平台Unicode兼容性的最佳策略是在UTF-8内部使用单字节字符。当需要调用Windows API函数时,请将其转换为UTF-16,并始终调用*W
变量。大多数非Windows平台已经使用UTF-8,因此使用UTF-8非常简单
对。您将为Windows API调用将UTF-8转换为UTF-16
大多数情况下,您将对UTF-8使用常规字符串函数--strlen
,strcpy
(ick),snprintf
,strtol
。它们可以很好地处理UTF-8字符。对UTF-8使用char*
,否则您将不得不强制转换所有内容
请注意,下划线版本(如\u mbstowcs
)不是标准版本,它们的命名通常不带下划线,如mbstowcs
很难给出实际希望在Unicode字符串上使用运算符[]
的示例,我的建议是远离它。类似地,对字符串进行迭代的用途也很少:
- 如果您正在解析一个字符串(例如,字符串是C或JavaScript代码,可能您需要语法高亮显示),那么您可以逐字节完成大部分工作,而忽略多字节方面
- 如果您正在执行搜索,您还将逐字节执行此操作(但请记住先进行规范化)<