作为介绍,我从事 Java 工作,过去也从事过相当多的 C 工作。
在 Java 中,一个 String
literal 可以包含任何一组字素,只要你可以在你的编辑环境中输入它们;然后,所述编辑环境将以当时使用的任何字符编码保存您的源文件。
在运行时,只要编译器支持编码,字节码代表所有String
文字作为一组 char
s,其中一个 char
代表一个 UTF-16 编码单元。 (因此,BMP 之外的 Unicode 代码点需要两个 char
s;您可以使用 char
获得代表 BMP 之外的 Unicode 代码点所必需的 Character.toChars()
数组。
你有一个字符编码类( Charset
),编码一个char
序列的过程s 到字节序列 ( CharsetEncoder
) 以及反向 ( CharsetDecoder
)。因此,无论您的源/目标使用何种字符编码,无论它是文件、套接字还是其他任何东西,您都可以根据需要进行编码/解码。
现在,让我们假设 C++11。它介绍了std::u32string
, std::u16string
;据我所知,这些是 std::basic_string<char32_t>
的“别名”和 std::basic_string<char16_t>
,它们的最终效果是在运行时,您声明的字符串常量(使用 u""
和 U""
)由分别表示 UTF-16 或 UTF-32 代码单元的 16 位或 32 位实体组成。还有u8""
(后者的 basic_string
类型是什么,因为它没有固定长度?)。
其他重点:UTF-16有两个变体,LE和BE; java 确实是 BE,因为在字节码级别,一切都是 BE。是否char{16,32}_t
取决于代码中的字节序?
但即使经过几个小时的搜索,我也找不到答案:作为标准,C++11 能否做标准 JDK 做的事情,即将任何字符串常量转换为合适的字节序列,并在给定字符的情况下反向转换编码?我怀疑这变得更加困难,因为在运行时基本上有三种字符串文字表示,甚至没有去 char *
这基本上是一个字节数组...
(编辑:添加到相关 javadoc 的链接)
最佳答案
您可以通过使用 codecvt locale facet 进行转换。
用法有点不直观,但这是我所做的:
/** Convert utf8 stream to UCS-4 stream */
u32string decode(string utf8)
{
std::wstring_convert<std::codecvt_utf8<char32_t>,char32_t> convert;
return convert.from_bytes(utf8);
}
/** Convert UCS-4 stream to utf8 stream */
string encode(u32string ucs4)
{
std::wstring_convert<std::codecvt_utf8<char32_t>,char32_t> convert;
return convert.to_bytes(ucs4);
}
虽然它需要一个像样的编译器,但对我来说只有 clang 可以正常工作,gcc 编译但生成无效结果(较新版本的 gcc 可能没问题)。
关于java - Unicode码指向字节并反转: how do you do that in C++?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22817699/