关于编码和乱码

关于编码和乱码,简单讲一下

 

通常问这类问题的人是混淆了若干个不同的概念,并且他们自己也没有意识到自己混淆了这些概念。

1.终端显示字符的编码(Windows下终端是cmd,Linux下是各种terminal,远程登录是putty或者xshell)

2.shell 环境的编码。比如中文版Windows用的是gbk(向下兼容gb2312),大多数Linux发行版使用的是utf-8

shell是用户与作业系统之间的交互层,用户修改其环境,设置或 取消shell的环境变量,迎合用户的需要和爱好。 

 shell本身就是一个电脑程序,用C语言编写,为协助用户与作业系统之间通讯而设。

 

3. 文本文件的编码。这个通常取决于你的编辑器,而且有的编辑器支持多种编码的话,你可以再文本开头位置指定编辑器使用特定编码。

    比如#-*-coding:utf8-*-

   上面这一句告诉Python解释器:此源程序是utf-8编码的。。

   vim看到这行会默认将这个脚本认定为utf-8兼容编码格式。

   s='你好'。这个S字符串还是以unicode编码的。文件的编码与字符串的编码是两回事。在开头声明的只是文件的编码方式。

 


4.应用程序的内部编码。一个字符串,作为数据只是一个字节数组;但是作为字符的数组,就有一个解析方式。java和python的内部字符编码是utf-16,

   python和java 都支持用不同的编码来对字节数组进行decode来得到字符数组。

 

为了要能够正常地显示中文,以下条件缺一不可:

1.终端和环境的编码一致(本机通常是一致的,不一致常常出现在远程登录);如果不一致就需要有编辑器或者文本阅读器做一个兼容两者的转换。

2.编辑器能够认识文本编码。

3.系统拥有能显示这种字符的字体。


 

文件编码:

Python 2.0x上默认的文件编码是ASIC码,ASIC不支持中文,所以中国有了GB2312. 

UTF8 是UniCode的一个扩展集。UniCode是万国编码,包含各个国家的编码。Windows默认的中国软件编码是GBK。GBK向下兼容GB2312.

ASIC码:占一个字节

UTF8: 英文字符占1个字节,中文字符占3个字节,UTF8 是可变长的。

UniCode:占2个字节

GBK----------(decode)-------->UniCode------(encode)------------->UTF8

Python 3.0默认编码是Unicode

 

1. 字符编码简介

1.1. ASCII

ASCII(American Standard Code for Information Interchange),是一种单字节的编码。计算机世界里一开始只有英文,而单字节可以表示256个不同的字符,可以表示所有的英文字符和许多的控制符号。

 

1.2. Unicode

 

后来,有人开始觉得太多编码导致世界变得过于复杂了,让人脑袋疼,于是大家坐在一起拍脑袋想出来一个方法:所有语言的字符都用同一种字符集来表示,这就是Unicode。

 

最初的Unicode标准UCS-2使用两个字节表示一个字符,所以你常常可以听到Unicode使用两个字节表示一个字符的说法。但过了不久有人觉得256*256太少了,还是不够用,于是出现了UCS-4标准,它使用4个字节表示一个字符,

 

UTF-8是一种很别扭的编码,具体表现在他是变长的,并且兼容ASCII,ASCII字符使用1字节表示。然而这里省了的必定是从别的地方抠出来的,你肯定也听说过UTF-8里中文字符使用3个字节来保存吧?4个字节保存的字符更是在泪奔

 

 

 

编码与解码

 

首先,明确一点,计算机中存储的信息都是二进制的
 
编码/解码本质上是一种映射(对应关系),比如‘a’用ascii编码则是65,计算机中存储的就是00110101,但是显示的时候不能显示00110101,还是要显示'a',但计算机怎么知道00110101是'a'呢,这就需要解码,当选择用ascii解码时,当计算机读到00110101时就到对应的ascii表里一查发现是'a',就显示为'a'

 

编码:真实字符与二进制串的对应关系,真实字符→二进制串;解码:二进制串与真实字符的对应关系,二进制串→真实字符

 

1.3. UnicodeASCII & UTF-8

大家熟知的ASCII以1字节8个bit位表示一个字符,首位全是0,表示的字符集明显不够

 

unicode编码系统是为表达任意语言而设计的,为了防止存储上的冗余(比如,对应ascii码的部分),其采用了变长编码,但变长编码给解码带来了困难,无法判断是几个字节表示一个字符
UTF-8是针对unicode变长编码设计的一种前缀码,根据前缀可判断是几个字节表示一个字符

 

 

如果一个字节的第一位是0,则这个字节单独就是一个字符;如果第一位是1,则连续有多少个1,就表示当前字符占用多少个字节。

 

比如"严"的unicode是4E25(100111000100101),4E25处在第三行的范围内(0000 0800-0000 FFFF),因此"严"的UTF-8编码需要三个字节,即格式是"1110xxxx 10xxxxxx 10xxxxxx"。然后,从"严"的最后一个二进制位开始,依次从后向前填入格式中的x,高位补0,得到"严"的UTF-8编码是"11100100 10111000 10100101"。

 

posted on 2017-08-03 17:39  momo8238  阅读(328)  评论(0编辑  收藏  举报