文章目录
  1. 1. ASCII
  2. 2. Unicode
  3. 3. UTF-8
  4. 4. unicode字节序

内容来源于 http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html

ASCII

ASCII is the American Standard Code for Information Interchange
ASCII编码用一个字节来表示一个字符, 总共定义了128个字符的编码(包括大小写的英文字母,特殊符号,控制字符)

Unicode

由于不同的国家使用不同的字符
即使都采用256个符号的编码方式,不同的编码方式会导致相同的数字可能对应不同的符号

有的语言使用的符号远远超过了256个字符,所以就必须采用多个字节来表示一个符号
例如简体中文常见的编码方式是GB2312

如上所述,世界上存在多种编码方式,同一个二进制可能被解释为不同的符号,
因此要查看一个文件,就必须要知道字符的编码方式,否则用错误的编码方式就会出现乱码
并且如果一个文件里面使用了多种语言,那么由于编码方式不同,也会出现乱码

为了解决以上问题,就定义了一种编码,可以将世界上所有的符号都纳入其中,
每个符号都包含一个独一无二的编码, 这就是Unicode
例如:
U+0041表示英语的大写字母 ‘A’
U+4E2D表示汉字 ‘中’

unicode 只是一个符号集, 只规定了符号的二进制代码,却没有规定这个二进制代码该如何存储
比如汉字 ‘国’的unicode编码为 0x56fd, 至少需要用2个字节才能存储,表示其他符号可能需要更多的字节

有如下两个问题需要解决:

  1. 如何区分unicode和ascii?
  2. 计算机怎么知道3个字节表示一个符号,或者是3个字节分别表示3个符号?

如果统一规定每个字符用4个字符表示,那么每个英文字符都有3个字节为0, 这样极大地浪费存储空间

UTF-8

UTF-8 只是 unicode的一种实现方式之一
UTF-8的特点: 采用变长编码,它可以使用1~4个字节表示一个符号

编码规则:

  1. 对于单字节的符号,字节的第一位设为0, 后面7位为这个字符的unicode码
    因此ASCII可以看作UTF-8的子集
  2. 对于大于n字节的符号(n > 1)
    第一个字节的前n位都设置为1,第n+1位设为0
    后面的字节前两位一律10
    其余的位用字符的unicode填充
unicode 符号范围 UTF-8编码字节数 UTF-8编码方式
十六进制 - 二进制
0000 0000 - 0000 007F 1 0xxxxxxx
0000 0080 - 0000 07FF 2 110xxxxx 10xxxxxx
0000 0800 - 0000 FFFF 3 1110xxxx 10xxxxxx 10xxxxxx
0001 0000 - 0010 FFFF 4 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
0020 0000 - 03FF FFFF 5 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
0400 0000 - 7FFF FFFF 6 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

转换示例:
例如: unicode 0x4F60, 表示中文 ‘你’
从上表可知 0x4F60 在UTF-8编码下需要用3个字节编码
3字节的UTF-8编码格式为 1110 xxxx 10xx xxxx 10xx xxxx
0x4F60的二进制表示为 0100 1111 0110 0000
填充到3字节的UTF-8格式中得到:

1
2
1110 xxxx 10xx xxxx 10xx xxxx
0100 11 1101 10 0000

1110 0100 1011 1101 1010 0000
即 e4bda0

下面使用iconv 和 xxd 工具来验证:

将unicode转换为UTF-8编码,可用如下命令实现:
例如: unicode 0x4E25

1
2
3
4
5
6
7
8
echo "25 4e" | xxd -r -p | iconv -f UNICODE -t UTF-8 | xxd -p
输出结果为: e4b8a5
xxd -r -p的输入字符串为 "25 4e", 低字节在前,高字节在后
输出结果也是第字节在前,高字节在后, 所以 e4为低字节, a5为高字节
echo "604f" | xxd -r -p | iconv -f UNICODE -t UTF-8 | xxd -p
输出结果为: e4bda0

unicode字节序

对于unicode 0x4F60, 有两个字节0x60和0x4F
如果采用big endian方式存储, 则第一个字节为0x4F,第二个字节为0x60
如果采用little endian方式存储, 则第一个字节为0x60,第二个字节为0x4F

unicode规范定义,每个文件的前面加入两个字节表示编码顺序
如果文件前两个字节分别是 fe ff, 则表示big endian
如果文件前两个字节分别是 ff fe, 则表示little endian

例:
新建一个文本文档,文件内容为 ‘你’, 编码格式为UTF-8

1
2
3
4
$ cat test.txt
$ file test.txt
test.txt: UTF-8 Unicode text

转换为unicode编码:

1
2
3
4
5
$ iconv -f UTF-8 -t UNICODE test.txt > test_unicode.txt
$ file test_unicode.txt
test_unicode.txt: Little-endian UTF-16 Unicode text, with no line terminators
$ xxd -g 1 test_unicode.txt
00000000: ff fe 60 4f 0a 00

文章目录
  1. 1. ASCII
  2. 2. Unicode
  3. 3. UTF-8
  4. 4. unicode字节序