[转]vim打开中文(gbk)乱码

转自:http://www.cnblogs.com/hopeworld/archive/2011/04/20/2022331.html

Vim有四个跟字符编码方式有关的选项,encoding、fileencoding、fileencodings、termencoding(这些选项设置请参考Vim文档中encoding-names章节),它们的意义如下:

  • encoding
    encoding是Vim内部使用的字符编码方式,包括Vim的buffer(缓冲区)、菜单文本、消息文本等。默认是根据你的locale选择。VIM用户手册上建议只在.vimrc中改变它的值,事实上似乎也只有在.vimrc中改变它的值才有意义。你可以用另外一种编码来编辑和保存文件,如你的vim的encoding为utf-8,所编辑的文件采用cp936编码,vim会自动将读入的文件转成utf-8(vim的能读懂的方式),而当你写入文件时,又会自动转回成cp936(文件的保存编码)。
  • fileencoding
    Vim中当前编辑的文件的字符编码方式,Vim保存文件时也会将文件保存为这种字符编码方式(不管是否新文件都如此)。
  • fileencodings
    Vim自动探测fileencoding的顺序列表,启动时会按照它所列出的字符编码方式逐一探测即将打开的文件的字符编码方式,并且将 fileencoding 设置为最终探测到的字符编码方式。因此最好将Unicode 编码方式放到这个列表的最前面,将拉丁语系编码方式 latin1放到最后面。
  • termencoding
    Vim所工作的终端(或者 Windows的Console窗口)的字符编码方式。如果vim所在的term与vim编码相同,则无需设置。如其不然,你可以用vim的termencoding选项将自动转换成term的编码.这个选项对GUI模式Vim(GVim)无效,而对Console模式的Vim而言就是Windows控制台的代码页,并且通常我们不需要改变它。

现在来看看Vim的多字符编码方式支持是如何工作的:

  1. 启动Vim,根据.vimrc文件中设置的encoding的值来设置buffer、菜单文本、消息文的字符编码方式。
  2. 读取需要编辑的文件,根据fileencodings中列出的字符编码方式逐一探测该文件编码方式。并设置fileencoding为探测到的,看起来是正确的字符编码方式。
  3. 对比fileencoding和encoding的值,若不同则调用iconv将文件内容转换为encoding所描述的字符编码方式,并且把转换后的内容放到为此文件开辟的 buffer 里,此时我们就可以开始编辑这个文件了。注意,完成这一步动作需要调用外部的 iconv.dll,你需要保证这个文件存在于$VIMRUNTIME或者其他列在PATH环境变量中的目录里。
  4. 编辑完成后保存文件时,再次对比fileencoding和encoding的值。若不同,再次调用iconv将即将保存的buffer中的文本转换为fileencoding所描述的字符编码方式,并保存到指定的文件中。同样,这需要调用iconv.dll由于Unicode能够包含几乎所有的语言的字符,而且Unicode的UTF-8编码方式又是非常具有性价比的编码方式 (空间消耗比 UCS-2 小),因此建议encoding的值设置为utf-8。这么做的另一个理由是encoding设置为 utf-8 时,Vim 自动探测文件的编码方式会更准确 (或许这个理由才是主要的 ;)。我们在中文Windows里编辑的文件,为了兼顾与其他软件的兼容性,文件编码还是设置为GB2312/GBK比较合适,因此fileencoding建议设置为chinese(chinese是个别名,在Unix里表示gb2312,在Windows里表示cp936,也就是GBK的代码页)。

当vim在utf-8的local下打开gbk文件时,显示的是乱码,可以在~/.vimrc文件中加入如下代码来解决:

这一行的作用是告诉vim,打开一个文件时,尝试utf8,gbk两种编码,vim只需要扫描文件的前一段,就可以根据文件里面的数据判断出文件是否用的是utf8或者gbk编码。如果不指定这一行,则vim只会用当前编码 (locale)来打开文件,因为locale是UTF-8,而文件是gbk,所以打开是乱码。

一般vim打开中文文件时出现乱码时可以用下面的方法来解决:

这样设置的原因说明如下:vim里面的编码主要跟三个参数有关:enc(encoding), fenc(fileencoding)和fencs(fileencodings)。其中fenc是当前文件的编码,也就是说,一个在vim里面已经正确显示了的文件(前提是你的系统环境跟你的enc设置匹配),你可以通过改变 fenc后再w来将此文件存成不同的编码。比如说,我:set fenc=utf-8然后:w就把文件存成utf-8的了,:set fenc=gb18030再:w就把文件存成gb18030的了。这个值对于打开文件的时候是否能够正确地解码没有任何关系。fencs就是用来在打开文件的时候进行解码的猜测列表。文件编码没有百分百正确的判断方法,所以vim只能猜测文件编码。比如我的vimrc里面这个的设置是:

所以我的vim每打开一个文件,先尝试用utf-8进行解码,如果用utf-8解码到了一半出错(所谓出错的意思是某个地方无法用utf-8正确地 解码),那么就从头来用gb18030重新尝试解码,如果gb18030又出错(注意gb18030并不是像utf-8似的规则编码,所以所谓的出错只是 说某个编码没有对应的有意义的字,比如0),就尝试用utf-16,仍然出错就尝试用big5。这一趟下来,如果中间的某次解码从头到尾都没有出错,那么 vim就认为这个文件是这个编码的,不会再进行后面的尝试了。这个时候,fenc的值就会被设为vim最后采用的编码值,可以用:set fenc?来查看具体是什么。

当然这个也是有可能出错的,比如你的文件是gb18030编码的,但是实际上只有一两个字符是中文,那么有可能他们正好也能被utf-8解码,那么这个文件就会被误认为是utf-8的导致错误解码。

至于enc,其作用基本只是显示。不管最后的文件是什么编码的,vim都会将其转换为当前系统编码来进行处理,这样才能在当前系统里面正确地显示出 来,因此enc就是干这个的。在windows下面,enc默认是cp936,这也就是中文windows的默认编码,所以enc是不需要改的。在 linux下,随着你的系统locale可能设为zh_CN.gb18030或者zh_CN.utf-8,你的enc要对应的设为gb18030或者 utf-8(或者gbk之类的)。

最后再来说一下新建空文件的默认编码。看文档好像说会采用fencs里面的第一个编码作为新建文件的默认编码。但是这里有一个问题,就是fencs 的顺序跟解码成功率有很大关系,根据我的经验utf-8在前比gb18030在前成功率要高一些,那么如果我新建文件默认想让它是gb18030编码怎么 办?一个方法是每次新建文件后都:set fenc=gb18030一下,不过我发现在vimrc里面设置fenc=gb18030也能达到这个效果。

Leave a Reply

Your email address will not be published.