专栏首页后端技术探索vim 乱码问题解决及原理全面分析

vim 乱码问题解决及原理全面分析

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文件中加入如下代码来解决:

1

set fencs=utf-8,gbk

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

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

1

set fileencoding=gb18030 set fileencodings=utf-8,gb18030,utf-16,big5

这样设置的原因说明如下: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里面这个的设置是:

1

set fileencodings=utf-8,gb18030,utf-16,big5

所以我的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也能达到这个效果。

本文分享自微信公众号 - nginx(nginx-study),作者:希望国度

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2015-08-13

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 重磅|微信发布2015微信生活白皮书

    今天在腾讯全球合作伙伴大会微信分论坛上,微信团队对外做了“微信·生活”的分享。现在,就让我们一起,从微信视角来看看中国人的喜怒哀乐、衣食住行。以下是报告的全文,...

    后端技术探索
  • 简述架构设计原则

    1.全面解耦原则:对业务进行抽象建模,业务数据与业务逻辑解耦,软硬件解耦,平台和产品解耦,系统各部件解耦。模块、组件高内聚,低耦合。

    后端技术探索
  • 58同城高性能移动Push推送平台架构演进之路

    关于作者:孙玄,58赶集集团系统架构师,技术负责人,技术委员会架构组主任,也是58同城即时通讯、C2C技术负责人,负责58核心系统的架构以及优化工作。分布式系统...

    后端技术探索
  • 计算机英语

    Deprecated Interfaces:过时的接口 reactor:n. [化工] 反应器; [核] 反应堆; 起反应的人; 原子炉; Decouple...

    城市中的游牧民族
  • 【带着canvas去流浪(6)】绘制雷达图

    使用原生canvasAPI绘制雷达图。(截图以及数据来自于百度Echarts官方示例库【查看示例链接】)。

    大史不说话
  • GitHub Action 新上线 WPF .NET Core 自动构建模板

    在很土豪的微软免费给大家提供 GitHub 的构建服务器受到了小伙伴们的一堆好评之后,微软最近推出了 WPF 的 .NET Core 版本的模板,可以快速上手 ...

    林德熙
  • Orion猎户座的继承者— Scorpius天蝎座

    时见疏星
  • python中optparse的使用

    写爬虫的时候其实一开始都是从写一个命令行程序开始的,然后慢慢的扩展,扩展到一个完整的系统,当然根据现在的经验,这样扩展起来的系统,不如直接设计好系统的整体结构来...

    the5fire
  • 假日出行必备:专家解析如何在公共Wi-Fi网络下保护个人隐私

    “用指尖改变世界” ? 对于外出的我们来说,公共Wi-Fi网络在很多方面都是很棒的。因为它是免费的,能够节省我们很多的移动数据流量,并且提供更快的下载速度。 然...

    企鹅号小编
  • 致全体中国知识分子的一封信——读完惊出一身冷汗

    看中国站在哪里看,这是出发点问题,更是利益问题。不同的出发点和利益立场会有完全不同的结论。

    钱塘数据

扫码关注云+社区

领取腾讯云代金券