关于字符编码

很久以前有一群人,他们认为可以用8个小灯泡表示世间万物。每个小灯泡分为亮。。和不亮。。后来这组灯泡(8个)就发展成了计算机中的字节。

ASCII编码

要知道的是一个字节(Byte)8位(bit),每一位有0和1两种值,这样就可以组成256种不同的状态。

所以人们就将1-127号的状态表示不同的字符,包括的"换行","空格",英文和数字字符。这就是ANSI(AMERICAN NATIONAL STANDARDS INSTITUTE,美国国家标准学会)制定的ASCII(American Standard Code for Information Interchange,美国信息互换标准代码)编码方案,用来保存英文字符。后来人们又扩展了128-255号的状态,包括一些新的字符,比如"-","/"什么的。

GB*编码

可惜,等到中国人民使用计算机的时候,已经没有可利用的状态表示汉字了,那我们的6000多个常用汉字怎么存?我们的办法是:把127号后面的字符取消掉,并规定,一个小于127的字符意义于原来一样,两个大于127的字符连在一起就表示一个汉字,前面一个字节(称之为高字节)从0xA1用到0xF7,后面一个字节(低字节)从0xA1到0xFE,这样我们就可以组合出大约7000多个简体汉字了,同时我们还把一些数学符号、罗马字符、日本的假名也都编了进去,连之前有的数字、标点、字母都重新编成了两个字节,这就是所谓的全角字符,原来的127号以下的就称之为半角字符。这种字符就是GB2312,GB2312是对ASCII的扩展,两个字节长的汉字字符和一个字符长的英文字符并存在一套编码方案里。

储存方案如下图:
GB*编码

但中国的汉字实在太多,后来又对GB2312进行了扩展,低字节就没有要求必须大于127了,只要第一个字节大于127就可以固定表示一个汉字,这个编码方案就是GBK,GBK包含了GB2312的所有内容,同时增加了20000个新汉字(包括繁体字)和符号。

后来少数名族也开始使用计算机,我们又对GBK进行了扩充,新的方案叫做GB18030,现在就好了,中国人民的悠久历史可以全部存到计算机中啦。

可是后来问题又来了,全世界很多国家都像中国一样搞了一套自己的编码标准,互相之间一点也不兼容,用国外的软件除非安装一套他们的编码系统,否则就用不了。

肿么办?

UNICODE编码

还好,这时ISO(国际标准化组织)出现了,废弃了所有地区性的编码方案,重新搞了一个包含地球上所有字符的编码!这就是UNICODE,但要注意的是UNICODE并不是一种具体的编码方案,UNICODE只是定义了字符的集合和唯一确定的编号,具体储存为什么样的字节流,取决于字符编码的方案,比如UTF-8和UTF-16,还有上述的GB18030。也就是说,虽然每个字符在UNICODE字符集种能找到唯一的编号,但最终决定字符流的是具体的字符编码。例如,同样的字符"A",UTF-8得到的字节流是0x41,UTF-16得到得是0x00 0x41。

从下图可以看到储存方式的不一样:
储存方式

UTF-8是目前使用得一套最广泛的UNICODE编码,它使用1-4个字节来编码字符,单字节和ASCII一样,对于其他字符,使用2-4个字节表示,比如汉字就用了3个字节表示。

GB18030编码,覆盖了UNICODE所有的字符,因此也算是一种UNICODE编码。只不过他的编码方式并不像UTF-8或者UTF-16一样,将Unicode字符的编号通过一定的规则进行转换,而只能通过查表的手段进行编码。

---- 以上内容写于2014年7月

Golang与字符编码

Go原生支持UNICODE,默认使用UTF-8编码的字符组成其字符串(UTF-8的发明者就是Go的作者,也就是Unix的作者Ken)。Go使用rune来存储字符串,它是int32的别名,因为一个UTF-8字符的长度可能是1,2,3,4个字节,所以如果要统计字符数,就需要计算的是rune的个数而不是字节数了。字符数和字节数只有在是字符串只由ASCII字符组成时才是一样的。

下面是一个中文字符串的示例,它表示出Go中字符串中不同字符占用长度不一样。

str := "你好,世界"
fmt.Println("rune len:", len([]rune(str)))   // 5
fmt.Println("int32 len:", len([]int32(str))) // 5
fmt.Println("Byte len", len(str))            // 15

用Go抓取网页的时候,当页面的编码不是UTF-8时,也许你需要使用 golang.org/x/text/transform 这个包做下转换。

参考

https://zh.wikipedia.org/wiki/字符编码
http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html
http://blog.wuxu92.com/golang-character-set-and-encoding

标签: golang, ascii, unicode

添加新评论