概述
目录
- 版权
- Unicode
- Java
- Go
- Windows C
- 相关文章
- 参考
版权
本文为原创, 遵循 CC 4.0 BY-SA 版权协议, 转载需注明出处: https://blog.csdn.net/big_cheng/article/details/123441548.
Unicode
unicode 给地球上每一个字符(character) 分配一个整数, 这些整数的范围称为codespace(编码空间; [参考1] 2.4 Code Points and Characters). 空间里的每个整数称为一个code point(编码点).
在上世纪unicode 总共容纳了几万个字符, 当时用2个字节(uint16, 0~65535) 可以表示每个code point. 后来字符越来越多容纳不下, 为保持兼容, 增加一个uint16(即用一对uint16) 来表示超出范围的新字符. 这种编码形式称为UTF-16, 其中每个uint16(即2个字节) 称为其code unit(编码单位; [参考1] 2.5 Encoding Forms).
unicode 还有UTF-32 和UTF-8 两种编码形式. 前者固定用4个字节(定长) 来表示一个字符, 其编码单位(code unit)=4字节; 后者用1到4个字节(变长) 来表示一个字符, 其code unit=1字节.
unicode 目前(14.0.0) code point 的范围是0~0x10FFFF(1,114,111, 21比特). 每64K(即65536, uint16) 划分为一个plane(平面; [参考1] 2.8 Unicode Allocation), 0~16共有17个平面(65536*17=1,114,112). 其中平面0(即上世纪的code point 范围, 0x0000~0xFFFF) 称为BMP(Basic Multilingual Plane, 基本多语言平面), 大部分人大部分时候使用的字符应该都不会超出该平面.
BMP 里0xD800~0xDFFF code point 称为surrogate code([参考1] 2.9 Details of Allocation Figure 2-14. Allocation on the BMP), UTF-16 用来编码BMP 之外所有平面的字符(这些称为supplementary character, 辅助字符). 规则见[参考2] 3.9 Unicode Encoding Forms Table 3-5. UTF-16 Bit Distribution(另, [参考3]):
- BMP 内的字符其编码 = code point 值
- BMP 外的字符其code point = 000uuuuu xxxxxxxx xxxxxxxx(21比特有内容), 则其编码 = 110110wwwwxxxxxx 110111xxxxxxxxxx, 其中wwww = uuuuu - 1
举例, 平面2 的第一个字符U+20000 “????” 字:
code point:
000uuuuu xxxxxxxx xxxxxxxx
00000010 00000000 00000000
wwww = uuuuu - 1 = 00010 - 1 = 0001
编码:
110110wwwwxxxxxx 110111xxxxxxxxxx
1101100001000000 1101110000000000
55360 56320
0xD840 0xDC00 - 均是surrogate code(0xD800~0xDFFF).
如上, 对于1个辅助字符, UTF-16 编码成2个surrogate codes - 称为surrogate pair(代理对, [参考1] 2.5 Encoding Forms - UTF-16). 代理对的开始code unit 也称为high/leading surrogate, 结束code unit 也称为low/trailing surrogate.
一般仅UTF-16 需考虑surrogate 问题, 例如遇到孤儿surrogate code(不成对的), 可以替换为unicode 替换字符(0xFFFD) 或者丢弃等. 注意, 单个surrogate code 仅仅是一个code point 而已, 没有对应的unicode 字符.
Java
Java 设计于上世纪, 所以String 是以UTF-16 code unit 为单位, 即String = 一组char, char = 2个字节([参考4]), char 范围0~65535.
public final class String implements ...... {
private final char value[];
......
}
通常的操作(包括下标) 都是针对这个char[], 当需要特殊处理code point 时有额外的方法.
String s1 = "A????B", s2 = "AuD840uDC00B";
// len=4, equal
System.out.printf("len=%d, %sn", s1.length(),
s1.equals(s2) ? "equal" : "not equal");
char c = s1.charAt(1);
System.out.println((int) c); // 55360
int i = s1.codePointAt(1), j = s1.codePointAt(2);
System.out.printf("0x%H, %dn", i, j); // 0x20000, 56320
String subs = s1.substring(2);
// "?B" len=2, [0] isLowSurrogate: true
System.out.printf(""%s" len=%d, [0] isLowSurrogate: %bn", subs, subs.length(),
Character.isLowSurrogate(subs.charAt(0)));
Go
Go 比较独特: 源代码只使用UTF-8; string 就是一组byte, 内部并没有预先拆成一个个rune 而是在运行时动态拆开.
s := "AU00020000B"
// len=6
fmt.Printf("len=%dn", len(s))
// [0] 0x41 [1] 0x20000 [5] 0x42
for i, c := range s {
fmt.Printf("[%d] 0x%X ", i, c)
}
fmt.Println()
可使用unicode/utf16 包来处理UTF-16.
Windows C
#include <windows.h>
#include <stdio.h>
int main()
{
WCHAR * s = L"A????B";
wprintf(L"len=%d, sizeof=%dn", wcslen(s), sizeof s); // len=4, sizeof=8
s++;
wprintf(L"high surrogate=%dn", (int)*s); // high surrogate=55360
s++;
wprintf(L"low surrogate=%dn", (int)*s); // low surrogate=56320
return 0;
}
Windows 也是类似Java, 使用UTF-16(wide character) 来支持unicode([参考5]).
相关文章
mysql | Incorrect string value: ‘xE7) xE5xA4xB1…‘
参考
[1] https://www.unicode.org/versions/Unicode14.0.0/ch02.pdf
General Structure
[2] https://www.unicode.org/versions/Unicode14.0.0/ch03.pdf
Conformance
[3] https://unicode.org/faq/utf_bom.html#utf16-3
Q: What’s the algorithm to convert from UTF-16 to character codes?
[4] https://docs.oracle.com/javase/specs/jls/se17/html/jls-3.html#jls-3.10.4
Java Language Specification
Chapter 3. Lexical Structure
[5] https://docs.microsoft.com/en-us/windows/win32/intl/unicode
[6] https://docs.microsoft.com/zh-cn/windows/win32/learnwin32/working-with-strings
操作字符串
最后
以上就是爱听歌悟空为你收集整理的hello, unicode surrogate版权UnicodeJavaGoWindows C相关文章参考的全部内容,希望文章能够帮你解决hello, unicode surrogate版权UnicodeJavaGoWindows C相关文章参考所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复