VIM乱码原因与解决方案

      VIM是一个很强大的文本编辑工具,虽然不容易上手,但是熟练以后就会非常喜欢这个编辑器;在vim的初始学习阶段,乱码经常是困扰新手的一个比较烦躁的问题,本文试图阐述乱码的原因和解决方案。

 

1 各种文本编码(encodings)

      世界上存在着N多种文本编码,ASCII、GBK、GB2312、GB18030、UTF8、UTF16等等。各种编码的来源与详细知识请参考以下的这篇文档,本文不再重复:
      http://hi.baidu.com/sinper9527/blog/item/4b6a58020b06c481d43f7c81.html

 

2 VIM的文本编码选项(enc/fenc/fencs/tenc)

      VIM有4个文本编码选项,以下一一介绍:

2.1 encoding(简写为enc):

      VIM内置的help文档对enc的主要描述如下:

      Sets the character encoding used inside Vim.  It applies to text in the buffers, registers, Strings in expressions, text stored in the viminfo file, etc.  It sets the kind of characters which Vim can work with.
      Normally 'encoding' will be equal to your current locale.  This will be the default if Vim recognizes your environment settings.  If 'encoding' is not set to the current locale, 'termencoding' must be set to convert typed and displayed text.

      大概意思是说enc是VIM内部使用的编码,应用在buffers,register等其他一些地方,它设置了vim可以用的文本编码。
      通常情况下,enc会和你的locale相同,即enc的默认值是由你的locale来决定的。如果enc没有被设置为locale的值,那么termencoding必须被设置为合适的值用来转换文本输入和显示。
      我的使用经验告诉我:enc是VIM的内部编码表示方式,包括buffers,register等一些地方,都用该编码来输入和显示文本。就是说VIM处理的是enc码文本流。关于termencoding选项,后面会讲。

2.2 fileencoding(简写为fenc):

      VIM内置的help文档对fenc的主要描述如下:

      Sets the character encoding for the file of this buffer. When 'fileencoding' is different from 'encoding', conversion will be done when reading and writing the file. When 'fileencoding' is empty, the same value as 'encoding' will be used (no conversion when reading or writing a file). When reading a file 'fileencoding' will be set from 'fileencodings'

      大概意思是说fenc设置为当前缓冲区内的文件的文本编码。当fenc和enc的设置不同时,VIM会在读取文件时自动将文件从fenc转换为enc,在写入文件时,又会将文件从enc转换为原来的fenc。当fenc的设置为空时,fenc会使用enc的值(所以在读写文件时不会引起编码转换)。当读取一个文件时,VIM会自动确定文件的编码,它依次尝试fencs列表中的每一种编码,如果尝试成功,就将成功的那个值设置为fenc的值。

      我的使用经验告诉我:fenc是VIM用来标识文件的文本编码的。VIM读取文件时,会自动确定文件的编码方式并将确定后的值赋值给fenc,写入文件时,最终是以fenc表示的编码方式写入文件的。
      具体确定fenc的值的方式为:当VIM读取一个文件时,它尝试从fencs列表中确定一个fenc的值,如果fencs中的值均不成功,则将fenc设置为空,表示fenc的值和enc相同。

2.3 fileencodings(简写为fencs):

      VIM内置的help文档对fencs的主要描述如下:

      This is a list of character encodings considered when starting to edit an existing file.  When a file is read, Vim tries to use the first mentioned character encoding.  If an error is detected, the next one in the list is tried.  When an encoding is found that works, 'fileencoding' is set to it.  If all fail, 'fileencoding' is set to an empty string, which means the value of 'encoding' is used.

      大概的意思和fenc中的解释差不多,不再赘述。

      我的使用经验告诉我:fencs是VIM确定fenc的值的来源之一。确定方式请参考fenc一节的描述。

2.4 termencoding(简写为tenc):

      VIM内置的help文档对tenc的主要描述如下:

      Encoding used for the terminal.  This specifies what character encoding the keyboard produces and the display will understand.  For the GUI it only applies to the keyboard ('encoding' is used for the display). When empty, the same encoding is used as for the 'encoding' option. This is the normal value.

      大概的意思是说tenc是终端所使用的文本编码选项。这个选项的值用于告诉VIM终端使用了哪种文本编码方式来用于文本输入和显示。如果该值为空,那么它被设置为enc的值。

      我的使用经验告诉我:tenc是用于告知VIM说终端是使用何种文本编码方式来作文本输入和显示的,也就是说,VIM需要理解你的键盘输入的文本是何种编码,也需要理解你的终端将用何种编码来显示文本,这样才能够正确的将文本输入到VIM中和显示在你的终端上。通常情况下,tenc的值和enc的值是等同的,除非你手工设置。

      如果你觉得这4个选项的描述过于繁琐,可以看一下下面给出的总结图:

vim

 

3 乱码的原因和解决方案

      也许你在阅读了上面一章节关于4个选项的描述后,虽然对概念有所理解,但可能还是有迷惑,不知道该如何正确设置这些选项的值,也可能不知道该如何解决乱码之类的问题。下面将说明乱码的原因和解决方案。 
      要介绍为何会乱码,我们先来看这3个关键的因素:
      (1)locale
      (2)enc
      (3)tenc 
      首先解释一下locale,如果你是Native Linux/Unix环境,那么对locale应该比较熟悉,它主要是用于设置你系统的语言环境的,其实Windows下也是一样的,Windows也有自己的locale设置(通常都是默认为zh_CN.GBK(或者GB2312/GB18030)。无论是哪个系统,你只要记住locale是用于设置系统级别的语言环境的就可以了。
      在Native Linux/Unix系统下,locale的值就是你Shell所设置的值,这时,最简单的情况是:enc的值设置为locale的值,tenc的值设置为enc的值,这3个值相同,所以是不会乱码的。
      在Windows系统下,情况则有所不同,因为你通常是用终端软件(例如putty/Xshell)从Windows登陆到Linux系统来使用VIM的,这个时候你可以认为locale的值是终端软件设置的值,当然locale本身的意义不是这样的,只不过这个时候Shell本身设置的locale对于Windows下的文本输入和显示是无关紧要的,所以你可以将Windows下的这个终端环境当做你VIM运行的环境,也就可以认为终端软件设置的locale和Linux下设置的locale是同类效果的,以Xshell来作为例子,设置如下:

tenc

      终端的这个Encoding设置是用于转换文本输入和显示的,如果你选择Default Language,那么XShell将使用Windows系统的locale值,通常都是zh_CN.GB2312,也就是说你输入的文本是以GB2312来编码的,显示的时候也是用GB2312来解释文本的。这里,我们就可以简单的认为,VIM的locale环境的编码的值为GB2312。
      解释完locale,我们来解释enc,enc是用于VIM做内部表示的,也就是说VIM内部处理的是以enc编码的文本流,所以实际上enc的值和显示是否乱码没有根本上的必要联系。只不过enc的值通常是tenc的取值来源而已,所以这里暂且将它列举为可能引起乱码的一个因素。
      最重要的其实是tenc的值,tenc是用于告诉VIM终端的locale值是什么的,那么,如果tenc告诉VIM的值是错误的话,那就肯定乱码了,所以其实乱码的最根本原因就是tenc的值和locale的值不同而造成的,具体来说:
     (1)在Native Linux/Unix环境下,locale的值与tenc的值不同
     (2)在Windows环境下,终端软件设置的Encoding(可以认为是locale)的值与tenc的值不同
      所以解决乱码的问题自然就是使得tenc的值和locale的值相同就可以了。在Native Linux/Unix环境下,最简单的就是将enc的值设置和locale相同就可以了,Windows下则主要是要将终端的Encoding值设置为与VIM的tenc值相同就可以了。不管你的fenc是何种编码,只要能通过iconv转换的,只要你设置了正确的终端Encoding值和VIM的tenc值,就不会乱码。举个例子来说:
      假如你要编辑的文件是UTF8格式的,那么其实不管你的终端的Encdoing的值如何设置,只要你将VIM的tenc值设置为与Encoding的值相同就可以正确显示了,其实这就是告诉VIM正确的识别终端的文本编码方式,就这么简单,大家统一口径,问题就解决了。
      请注意,上面的这个简单例子是假设你的文件的内容本身是正确的,如果内容本身不正确,那无论如何都不能显示正确,因为内容本身就是乱码。这个说法可能比较怪异,举个例子会相对明白些,新建一个文件时,请先确保你的tenc和你的终端的Encoding的值是一样的,否则你无论如何输入,都将显示乱码,原因是如果你的tenc和Encoding不同,那么VIM对你输入的文本的编码解释将是错误的,例如如果你的Encoding是GBK,这意味着你输入的GBK码,但是tenc设置的却是utf8,这意味着你告诉VIM你的输入是uft8码,这样VIM会把你的GBK码按utf8的编码方式来解释,最后在写入文件时,VIM将会以utf8转换为enc码(不管enc是什么编码)的方式来写入,但实际上应该是按GBK码转enc码的规则来写入文件,这很明显是错误的,所以文件本身的内容就是乱码了,你再怎么搞都是乱码。

 

4 选项的设置建议

      其实4个选项值的设置应该遵循简单而统一的原则,特别是VIM作为团队开发工具的时候,下面给出3种常用的配置:

      (1)中文环境GBK码
              将你的locale设置为zh_CN.gbk,然后将VIM设置如下:
              set enc=gbk
              set fencs=gbk,gb2312,gb18030,cp936,utf8
      (2)中文环境utf8码
              将你的locale设置为zh_CN.utf8,然后将VIM设置如下:
              set enc=utf8
              set fencs=utf8,gbk,gb2312,gb18030,cp936
      (3)英文环境ASCII码
              最简单的就这个了,啥都不用设置了,写英文文档就好了 ^_^

5 总结

(1)在文件本身内容正确的情况下,VIM的乱码是因为tenc的值和locale的值不同而造成的。
(2)如果你是在编辑到别人的文件时出现乱码,你可以不改你的locale(包括Native Linux Shell的locale和Windows下终端软件的Encoding两种情况),而只需要在VIM中临时改动你的tenc来适应locale就可以了。
(3)遵循简单而统一的编码配置,是团队开发的需要。

 

6 参考资料

(1)VIM help手册
(2)http://hi.baidu.com/sinper9527/blog/item/4b6a58020b06c481d43f7c81.html
(3)思想之地 http://be-evil.org/post-158.html

                                 参考资料版权归其作者所有,转载本文请注明出处

 

  • 1
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值