UTF-8、GBK、GBK2312等字符编码的区别和vim乱码等相关问题研究。

时间:2023-01-06 15:52:52

转自本人博客:xge技术博客

http://www.xgezhang.com/char_encodind_vim.html


关于字符编码的问题在做项目的时候经常都会出现,但一直没有很系统的研究过,今天早上系统的看了几篇文章。在此整理分享以下。

三种编码方式的简介:

    gb2312(又称为GB 2312-80)编码是一个简体中文字符集的中国国家标准,全称为《信息交换用汉字编码字符集·基本集》,又称为GB0,由中国国家标准总局发布,1981年5月1日实施。GB2312编码适用于汉字处理、汉字通信等系统之间的信息交换,通行于*;新加坡等地也采用此编码。*几乎所有的中文系统和国际化的软件都支持GB 2312。

    基本集共收入汉字6763个和非汉字图形字符682个。每个字符使用2个字节表示。

    gbk是汉字编码标准之一,全称《汉字内码扩展规范》(GBK即“国标”、“扩展”汉语拼音的第一个字母,英文名称:Chinese Internal Code Specification)

    GBK编码产生的原因:由于GB2312-80只收录了6763个汉字,有不少汉字,如部分在GB 2312-80推出以后才简化的汉字(如“啰”),部分人名用字(如中国前总
理*的“镕”字),*及香港使用的繁体字,日语及朝鲜语汉字等,并未有收录在内。中文电脑开发商,于是利用了GB 2312-80未有使用的编码空
间,收录了所有出现在Unicode 1.1及GB 13000.1-93之中的汉字,制定了GBK编码。

    在实际项目开发中,使用gb2312编码可能会使某些字符无法显示,所以推荐使用gbk编码。

    GBK编码和gb2312编码都是采用2字节存储每个字符。

    UTF-8:UTF-8:Unicode Transformation Format-8bit,。是用以解决国际上字符的一种多字节编码,它对英文使用8位(即一个字节),中文使用24为(三个字节)来编码。UTF-8包含全世界所有国家需要用到的字符,是国际编码,通用性强。
UTF-8编码的文字可以在各国支持UTF8字符集的浏览器上显示。如,如果是UTF8编码,则在外国人的英文IE上也能显示中文,他们无需下载IE的中文语言支持包。

    简单的说,对于汉字的显示,使用国标码(gbk,gb2312)会更加节省空间,但是相对来说通用性更差,使用utf-8编码存储汉字会比使用国标码增加一半的空间消耗,但通用性更好。

Linux下编码问题

    在Linux环境下经常会出现文件乱码的问题,这实际上就是因为文件编码,以Ubuntu为例,默认的字符编码为UTF-8,并且没有默认安装gbk和gb2312,所以需要我们进行安装和相应配置。

    首先了解下locale指令,它是将有关当前语言环境或全部公共语言环境的信息写到标准输出上,输入指令,应该是不能找到gbk内容。

    进行安装:

    sudo locale-gen zh_CN.GBK
    sudo locale-gen zh_CN.GB2312
    sudo locale-gen zh_CN.GB18030

    然后更新一下:

    sudo dpkg-reconfigure locales
    sudo locale-gen
    看到有zh_CN.GBK,说明安装成功。

Vim编码原理及乱码处理:   

    对应像vim这类的编辑器,还要另外加入两行配置文件,打开/etc/vim/vimrc文件,加上这两行内容。
    let &termencoding=&encoding
    set fileencodings=utf-8,gbk,gb18030,gb2312,big5
    然后就可以显示gbk,gb2312类的编码文件了。

    原理如下:(不感兴趣的就跳过吧,注意其没有涉及gvim,纯指字符终端下的vim)
    首先看四个vim中的参数:    
  • encoding:该选项使用于缓冲的文本(你正在编辑的文件),寄存器,Vim 脚本文件等等。你可以把 ‘encoding’ 选项当作是对 Vim 内部运行机制的设定。默认为当前系统的locale。
  • fileencodieng:Vim在保存新建文件时会根据fileencoding的设置编码来保存。如果是打开已有文件,Vim会根据打开文件时所识别的编码来保存,除非在保存时重新设置fileencoding。
  • fileencodings:该选项是vim写入文件时采用的编码类型。默认为自动辨认出来的编码(后面会讲到),系统会按顺序进行猜测。
  • termencoding:该选项代表输出到客户终端(Term)采用的编码类型,默认为空值。

    再来看一下常见情况下这三个关键点的值以及在这种情况下这3个变量的值:

    locale:目前大部分的Linux系统都以utf-8作为默认的locale了,这是兼容性最好的方式,可以在外部进行无损转换,locale 决定了vim中的encoding。
    文件的编码以及自动编码识别,这方面牵扯到各种编码的规则,就不一一细讲了。但需要明白的是,文件编码类型并不是保存在文件内的,也就是说没有任何描述性的字段来记录文档是何种编码类型的。因此我们在编辑文档的时候,要么必须知道这文档保存时是以什么编码保存的,要么通过另外的一些手段来断定编码类型,这另外的手段,就是通过某些编码的码表特征来断定,例如每个字符占用的字节数,每个字符的ascii值是否都大于某个字段来断定这个文件属于何种编码。
     这种方式vim也使用了,这就是vim的自动编码识别机制了。但这种机制由于编码各式各样,不可能每种编码都有显著的特征来辨别,所以是不可能100%准确的。对于我们GB2312编码,由于其中文是使用了2个acsii值高于127的字符组成汉字字符的,因此不可能把gb2312编码的文件与 latin1编码区分开来,因此自动识别编码的机制对于gb2312是不成功的,它只会将文件辨识为latin1编码。此问题同样出现在gbk,big5 上等。因此我们在编辑此类文档时,需要手工设定encoding和fileencoding。

     相反很好理解,如果文档编码为utf-8时,一般vim都能自动识别正确的编码。

     客户运行vim的终端所使用的编码类型:同第二条一样,这也是一个比较难以断定的关键点。第二个关键点决定着从文件读取内容和写入内容到文件 时使用的编码,而此关键点则决定vim输出内容到终端时使用的编码,如果此编码类型和终端认为它收到的数据的编码类型不同,则又会产生乱码问题。

    首先能肯定的一点是,不通过远程访问而是本地访问,locale相同,所以不会存在这类问题。

    但如果是远程登陆,问题就麻烦了,例如从1台locale为GB2310的系统(称作客户机)ssh到locale为utf-8的系统(称作服 务器)并开启vim编辑文档,在不加任何改动的情况下,服务器返回的数据为utf-8的,但客户机认为服务器返回的数据是gb2312的,按照 gb2312来解释数据,则肯定就是乱码了,这时就需要设置termencoding为gb2312来解决这个问题。