Vim 编码问题详解

Vim 编码问题详解

vim 中有 4 个与编码相关的配置,分别是 encodingtermencodingfileencodingfileencodings。在实际使用中任何一个配置有问题都可能会导致乱码,因此我们应该清楚每个配置的含义。

1. encoding

encoding 是 vim 内部使用的字符编码格式。vim 内部所有的 buffer寄存器脚本中的字符串等,都使用的是该配置的编码格式。如果文件的编码格式与内部编码格式不一致,则会先转为内部的编码格式,如果无法转换,则无法转换的字符会丢失。因此在设置内部编码时应该选择一种表现力足够的编码,即编码范围大的格式,比如 UTF-8。

由于 encoding 配置涉及 vim 中所有的字符的内部编码方式,因此,只能在 vim 启动的时候进行设置。如果没有特殊需求,请始终将 encoding 设置为 UTF-8

为了避免在非 UTF-8 的系统下(比如 Windows)菜单和系统提示出现乱码,可以进行如下配置:

set encoding=utf-8
set langmenu=zh_CN.UTF-8
language message zh_CN.UTF-8

2. termencoding

termencoding 是 Vim 用于屏幕时的编码格式,在显示的时候,vim 会把内部编码(encoding)转换为屏幕编码格式,然后再输出到屏幕。如果内部编码中含有无法转换为屏幕编码的字符,那么该字符就会变成问号,但是不会影响编辑操作。

比如,当在 Windows 中使用模拟终端远程连接服务器时,由于 Windows 中的模拟终端编码设置为 GBK 格式,而 Linux 中使用 UTF-8 编码,那么终端中的字符就会乱码,此时有两种方式可以解决此类乱码问题:

  1. 把 vim 的 encoding 改为 GBK,此时其内部的编码格式(buffer 中的编码格式)与终端的格式就一致了。
  2. 更改 termencoding 编码格式为 GBK,让 vim 将 buffer 中的字符在显示的时候转换为 GBK 编码,这样终端就可以正常显示了。

对于第一种解决方式,如果遇到编辑的文件中含有 GBK 无法表示的字符时,这些字符就会丢失。使用第二种方式的时候,虽然无法正常显示,但是仍然可以正常编辑(不会影响 buffer 中的内容)。故推荐使用第二种方式

对于图形界面的下的 Gvim,它的显示不依赖于终端,因此 termencoding 配置无意义。在 GTK2 下的 Gvim 中,termencoding 始终是 utf-8,不能修改。Windows 下的 Gvim 则忽略 termencoding 的配置。

3. fileencoding

当 Vim 从磁盘中读取文件时,会对文件编码格式进行检测,如果文件的编码方式和内部编码方式(encoding)不同,就会将其转换为内部编码格式。转换完毕后,Vim 会将 fileencoding 设置为文件的编码(检测过程中识别出的编码)。
当 vim 对文件进行保存时,如果 encoding(内部使用的编码) 和 fileencoding(文件编码) 不一致,就会进行编码转换,将 buffer 中的数据由 encoding 格式转换成 fileencoding 格式(即原本的文件格式)。

因此,我们可以通过打开文件后重新设置 fileencoding 来进行文件格式的转换,但是这有一个前提:就是 vim 可以正确识别出文件的编码格式,如果格式识别错误是无法通过更改 fileencoding 来进行转换的。

4. fileencodings

上面提到的文件编码检测是通过设置 fileencodings 实现的(注意是复数)。fileencodings 是一个逗号分割的列表,列表中的元素为编码格式名称。
当我们使用 vim 打开文件时,vim 会按顺序使用 fileencodings 中指定的编码尝试解码,如果成功,则使用该编码格式进行转码(由文件编码格式转换为内部编码格式 encoding),并设置 fileencoding 为该编码格式,如果失败就使用下一种方式尝试解码。

因此,我们在设置 fileencodings 的时候,一定要将编码严格的、解码不正确更容易失败的格式放在列表的前面,将宽松的,包容性好的格式放在后面。

例如,Latin1 是一种非常宽松的编码方式,任何一种编码方式的文本都可以使用它进行解码,不会解码失败,但是,会出现乱码(注意:解码失败 != 乱码)。因此,如果把 latin1 放到了列表的第一个,那么打开文件自动识别的 fileencoding 都是 latin1,都有可能出现乱码的情况。

以下推荐配置:

set fileencodings=ucs-bom,utf-8,cp936,gb18030,big5,euc-jp,euc-kr,latin1

如果 vim 自动检测的编码格式不正确,但是我们知道正确的编码格式,可以使用 ++enc=encoding_type 来打开文件::e ++enc=utf-8 filename

下面是对该配置的说明:

ucs-bom 是一种非常严格的编码,非该编码的文件几乎没有可能被误判为 ucs-bom,因此放在第一位。

utf-8 也相当严格,除了很短的文件外(例如许多人津津乐道的 GBK 编码的“联通”被误判为 UTF-8 编码的经典错误),现实生活中一般文件是几乎不可能被误判的,因此放在第二位。

接下来是 cp936 和 gb18030,这两种编码相对宽松,如果放前面的话,会出现大量误判,所以就让它们靠后一些。cp936 的编码空间比 gb18030 小,所以把 cp936 放在 gb18030 前面。

至于 big5、euc-jp 和 euc-kr,它们的严格程度和 cp936 差不多,把它们放在后面,在编辑这些编码的文件的时候必然出现大量误判,但这是 Vim 内置编码探测机制没有办法解决的事。由于中国用户很少有机会编辑这些编码的文件,因此还是要把 cp936 和 gb18030 提前以保证这些编码的识别。

最后是 latin1,它是一种极其宽松的编码,以至于我们不得不把它放在最后一位。不过可惜的是,当你碰到一个真的 latin1 编码的文件时,绝大部分情况下,它没有机会 fall-back 到 latin1,往往在前面的编码中就被误判了。不过,正如前面所说的,中国用户没有太多机会接触这样的文件。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值