1
- # 2.5 unicode — Unicode码点 、UTF-8/16编码 #
1
+ # 2.5 unicode — Unicode 码点 、UTF-8/16 编码 #
2
2
3
3
世界中的字符有许许多多,有英文,中文,韩文等。我们强烈需要一个大大的映射表把世界上的字符映射成计算机可以阅读的二进制数字(字节)。
4
4
这样,每个字符都给予一个独一无二的编码,就不会出现写文字的人和阅读文字的人编码不同而出现无法读取的乱码现象了。
5
5
6
- 于是Unicode就出现了 ,它是一种所有符号的编码映射。最开始的时候,unicode认为使用两个字节,也就是16位就能包含所有的字符了 。
7
- 但是非常可惜,两个字节最多只能覆盖65536个字符 ,这显然是不够的,于是附加了一套字符编码,即unicode4 .0,附加的字符用4个字节表示 。
8
- 现在为止,大概Unicode可以覆盖100多万个字符了 。
6
+ 于是 Unicode 就出现了 ,它是一种所有符号的编码映射。最开始的时候,unicode 认为使用两个字节,也就是 16 位就能包含所有的字符了 。
7
+ 但是非常可惜,两个字节最多只能覆盖 65536 个字符 ,这显然是不够的,于是附加了一套字符编码,即 unicode4 .0,附加的字符用 4 个字节表示 。
8
+ 现在为止,大概 Unicode 可以覆盖 100 多万个字符了 。
9
9
10
- Unicode只是定义了一个字符和一个编码的映射 ,但是呢,对应的存储却没有制定。
11
- 比如一个编码0x0041代表大写字母A,那么可能有一种存储至少有4个字节,那可能0x00000041来存储代表A 。
12
- 这个就是unicode的具体实现。unicode的具体实现有很多种 ,UTF-8和UTF-16就是其中两种 。
10
+ Unicode 只是定义了一个字符和一个编码的映射 ,但是呢,对应的存储却没有制定。
11
+ 比如一个编码 0x0041 代表大写字母 A,那么可能有一种存储至少有 4 个字节,那可能 0x00000041 来存储代表 A 。
12
+ 这个就是 unicode 的具体实现。unicode 的具体实现有很多种 ,UTF-8 和 UTF-16 就是其中两种 。
13
13
14
- UTF-8表示最少用一个字节就能表示一个字符的编码实现 。它采取的方式是对不同的语言使用不同的方法,将unicode编码按照这个方法进行转换 。
14
+ UTF-8 表示最少用一个字节就能表示一个字符的编码实现 。它采取的方式是对不同的语言使用不同的方法,将 unicode 编码按照这个方法进行转换 。
15
15
我们只要记住最后的结果是英文占一个字节,中文占三个字节。这种编码实现方式也是现在应用最为广泛的方式了。
16
16
17
- UTF-16表示最少用两个字节能表示一个字符的编码实现。同样是对unicode编码进行转换 ,它的结果是英文占用两个字节,中文占用两个或者四个字节。
18
- 实际上,UTF-16就是最严格实现了unicode4 .0。但由于英文是最通用的语言,所以推广程度没有UTF-8那么普及 。
17
+ UTF-16 表示最少用两个字节能表示一个字符的编码实现。同样是对 unicode 编码进行转换 ,它的结果是英文占用两个字节,中文占用两个或者四个字节。
18
+ 实际上,UTF-16 就是最严格实现了 unicode4 .0。但由于英文是最通用的语言,所以推广程度没有 UTF-8 那么普及 。
19
19
20
- 回到go对unicode包的支持,由于UTF-8的作者Ken Thompson同时也是go语言的创始人 ,所以说,在字符支持方面,几乎没有语言的理解会高于go了 。
21
- go对unicode的支持包含三个包 :
20
+ 回到 go 对 unicode 包的支持,由于 UTF-8 的作者 Ken Thompson 同时也是 go 语言的创始人 ,所以说,在字符支持方面,几乎没有语言的理解会高于 go 了 。
21
+ go 对 unicode 的支持包含三个包 :
22
22
23
23
* unicode
24
24
* unicode/utf8
25
25
* unicode/utf16
26
26
27
- unicode包包含基本的字符判断函数。utf8包主要负责rune和byte之间的转换。utf16包负责rune和uint16数组之间的转换 。
27
+ unicode 包包含基本的字符判断函数。utf8 包主要负责 rune 和 byte 之间的转换。utf16 包负责 rune 和 uint16 数组之间的转换 。
28
28
29
- 由于字符的概念有的时候比较模糊,比如字符(小写a)普通显示为a ,在重音字符中(grave-accented)中显示为à。
30
- 这时候字符(character)的概念就有点不准确了,因为a和à显然是两个不同的unicode编码 ,但是却代表同一个字符,所以引入了rune 。
31
- 一个rune就代表一个unicode编码,所以上面的a和à是两个不同的rune 。
29
+ 由于字符的概念有的时候比较模糊,比如字符(小写 a)普通显示为 a ,在重音字符中(grave-accented)中显示为à。
30
+ 这时候字符(character)的概念就有点不准确了,因为 a 和à显然是两个不同的 unicode 编码 ,但是却代表同一个字符,所以引入了 rune 。
31
+ 一个 rune 就代表一个 unicode 编码,所以上面的 a 和à是两个不同的 rune 。
32
32
33
- 这里有个要注意的事情,go语言的所有代码都是UTF8的,所以如果我们在程序中的字符串都是utf8编码的 ,但是我们的单个字符(单引号扩起来的)却是unicode的 。
33
+ 这里有个要注意的事情,go 语言的所有代码都是 UTF8 的,所以如果我们在程序中的字符串都是 utf8 编码的 ,但是我们的单个字符(单引号扩起来的)却是 unicode 的 。
34
34
35
- ## 2.5.1 unicode包 ##
35
+ ## 2.5.1 unicode 包 ##
36
36
37
- unicode包含了对rune的判断。这个包把所有unicode涉及到的编码进行了分类 ,使用结构
37
+ unicode 包含了对 rune 的判断。这个包把所有 unicode 涉及到的编码进行了分类 ,使用结构
38
38
39
39
``` golang
40
40
type RangeTable struct {
@@ -43,7 +43,7 @@ type RangeTable struct {
43
43
LatinOffset int
44
44
}
45
45
```
46
- 来表示这个功能的字符集。这些字符集都集中列表在table.go这个源码里面 。
46
+ 来表示这个功能的字符集。这些字符集都集中列表在 table.go 这个源码里面 。
47
47
48
48
比如控制字符集:
49
49
@@ -63,18 +63,18 @@ var _Pc = &RangeTable{
63
63
64
64
```
65
65
func IsControl(r rune) bool // 是否控制字符
66
- func IsDigit(r rune) bool // 是否阿拉伯数字字符,即1 -9
66
+ func IsDigit(r rune) bool // 是否阿拉伯数字字符,即 1 -9
67
67
func IsGraphic(r rune) bool // 是否图形字符
68
68
func IsLetter(r rune) bool // 是否字母
69
69
func IsLower(r rune) bool // 是否小写字符
70
70
func IsMark(r rune) bool // 是否符号字符
71
71
func IsNumber(r rune) bool // 是否数字字符,比如罗马数字Ⅷ也是数字字符
72
- func IsOneOf(ranges []*RangeTable, r rune) bool // 是否是RangeTable中的一个
72
+ func IsOneOf(ranges []*RangeTable, r rune) bool // 是否是 RangeTable 中的一个
73
73
func IsPrint(r rune) bool // 是否可打印字符
74
74
func IsPunct(r rune) bool // 是否标点符号
75
75
func IsSpace(r rune) bool // 是否空格
76
76
func IsSymbol(r rune) bool // 是否符号字符
77
- func IsTitle(r rune) bool // 是否title case
77
+ func IsTitle(r rune) bool // 是否 title case
78
78
func IsUpper(r rune) bool // 是否大写字符
79
79
```
80
80
@@ -90,44 +90,44 @@ func main() {
90
90
digit := rune (' 1' )
91
91
fmt.Println (unicode.IsDigit (digit)) // true
92
92
fmt.Println (unicode.IsNumber (digit)) // true
93
- letter := rune (' Ⅷ ' )
93
+ letter := rune (' Ⅷ ' )
94
94
fmt.Println (unicode.IsDigit (letter)) // false
95
95
fmt.Println (unicode.IsNumber (letter)) // true
96
96
}
97
97
```
98
98
99
- ## 2.5.2 utf8包 ##
99
+ ## 2.5.2 utf8 包 ##
100
100
101
- utf8里面的函数就有一些字节和字符的转换 。
101
+ utf8 里面的函数就有一些字节和字符的转换 。
102
102
103
- 判断是否符合utf8编码的函数 :
103
+ 判断是否符合 utf8 编码的函数 :
104
104
* func Valid(p [ ] byte) bool
105
105
* func ValidRune(r rune) bool
106
106
* func ValidString(s string) bool
107
107
108
- 判断rune的长度的函数 :
108
+ 判断 rune 的长度的函数 :
109
109
* func RuneLen(r rune) int
110
110
111
- 判断字节串或者字符串的rune数
111
+ 判断字节串或者字符串的 rune 数
112
112
* func RuneCount(p [ ] byte) int
113
113
* func RuneCountInString(s string) (n int)
114
114
115
- 编码和解码rune到byte
115
+ 编码和解码 rune 到 byte
116
116
* func DecodeRune(p [ ] byte) (r rune, size int)
117
117
* func EncodeRune(p [ ] byte, r rune) int
118
118
119
- ## 2.5.3 utf16包 ##
119
+ ## 2.5.3 utf16 包 ##
120
120
121
- utf16的包的函数就比较少了 。
121
+ utf16 的包的函数就比较少了 。
122
122
123
- 将int16和rune进行转换
123
+ 将 int16 和 rune 进行转换
124
124
* func Decode(s [ ] uint16) [ ] rune
125
125
* func Encode(s [ ] rune) [ ] uint16
126
126
127
- unicode有个基本字符平面和增补平面的概念,基本字符平面只有65535个字符 ,增补平面(有16个)加上去就能表示1114112个字符 。
128
- utf16就是严格实现了unicode的这种编码规范 。
127
+ unicode 有个基本字符平面和增补平面的概念,基本字符平面只有 65535 个字符 ,增补平面(有 16 个)加上去就能表示 1114112 个字符 。
128
+ utf16 就是严格实现了 unicode 的这种编码规范 。
129
129
130
- 而基本字符和增补平面字符就是一个代理对(Surrogate Pair)。一个代理对可以和一个rune进行转换 。
130
+ 而基本字符和增补平面字符就是一个代理对(Surrogate Pair)。一个代理对可以和一个 rune 进行转换 。
131
131
132
132
* func DecodeRune(r1, r2 rune) rune
133
133
* func EncodeRune(r rune) (r1, r2 rune)
0 commit comments