我需要以二进制模式读取以 UTF-16 编码编写的文件并将其转换为 UNICODE 代码点。我没有任何问题成功地映射 U+0000..U+FFFF 间隔的代码点。问题是,从 U+10000 到 U+10FFFF UTF-16 编码使用两部分来形成 Codepoint。
示例:这枚火箭“🚀”在 UTF-16 中编码为 0xD83D 0xDE80,形成 UNICODE 代码点:U+1F680。
由于 UTF-16 编码与从 U+0000 到 U+FFFF 之间的 UNICODE 代码点的数字完全相同,因此我编写代码只是将 UTF-16 读取转换为 UNICODE 代码点。问题出在 U+10000 及之后,因为我的程序将第一部分 (D83D) 理解为区间 U+0000 到 U+FFFF 之间的内容。
如何避免这个错误?我该怎么做我的代码才能让它知道它正在读取的片段还需要一个片段才能成功形成 UNICODE 代码点。
提前致谢!
您缺少的搜索词是“代理对”。请注意,以下代码不执行任何错误检查或边界检查。
int next_codepoint(uint16_t *text) {
int c1 = text[0];
if (c1 >= 0xd800 && c1 < 0xdc00) {
int c2 = text[1];
return ((c1 & 0x3ff) << 10) + (c2 & 0x3ff) + 0x10000;
}
return c1;
}
Unicode 规范对此进行了描述,该规范可从 Unicode 网站以及有关 UTF-16 的维基百科文章免费获取。还有许多可用于编解码器转换的库,例如 iconv。您正在尝试将 UTF-16 转换为 UTF-32,如果有帮助的话。
要么进行代理对转换,要么使用为您执行此操作的库,例如 iconv libunistring。参见:
https://www.gnu.org/software/libiconv/ https://www.gnu.org/software/libunistring/
示例:
https://github.com/drichardson/examples/blob/master/iconv/utf8-to-utf32.c