和所有的流行文本编辑器一样,Vim 可以很好的编辑各种字符编码的文件,这当然包括 UCS-2、UTF-8 等流行的 Unicode 编码方式。然而不幸的是,和很多来自 Linux 世界的软件一样,这需要你自己动手设置。

Vim 有四个跟字符编码方式有关的选项,encoding、fileencoding、fileencodings、termencoding(这些选项可能的取值请参考 Vim 在线帮助 :help encoding-names),它们的意义如下:

  • encoding: Vim 内部使用的字符编码方式,包括 Vim 的 buffer(缓冲区)、菜单文本、消息文本等。用户手册上建议只在 .vimrc 中改变它的值,事实上似乎也只有在 .vimrc 中改变它的值才有意义。
  • fileencoding: Vim 中当前编辑的文件的字符编码方式,Vim 保存文件时也会将文件保存为这种字符编码方式(不管是否新文件都如此)。
  • fileencodings: Vim 启动时会按照它所列出的字符编码方式逐一探测即将打开的文件的字符编码方式,并且将 fileencoding 设置为最终探测到的字符编码方式。因此最好将 Unicode 编码方式放到这个列表的最前面,将拉丁语系编码方式 latin1 放到最后面。
  • termencoding: Vim 所工作的终端(或者 Windows 的 Console 窗口)的字符编码方式。这个选项在 Windows 下对我们常用的 GUI 模式的 gVim 无效,而对 Console 模式的 Vim 而言就是 Windows 控制台的代码页,并且通常我们不需要改变它。

好了,解释完了这一堆容易让新手犯糊涂的参数,我们来看看 Vim 的多字符编码方式支持是如何工作的。

  1. Vim 启动,根据 .vimrc 中设置的 encoding 的值来设置 buffer、菜单文本、消息文的字符编码方式。
  2. 读取需要编辑的文件,根据 fileencodings 中列出的字符编码方式逐一探测该文件编码方式。并设置 fileencoding 为探测到的,看起来是正确的(注1)字符编码方式。
  3. 对比 fileencoding 和 encoding 的值,若不同则调用 iconv 将文件内容转换为 encoding 所描述的字符编码方式,并且把转换后的内容放到为此文件开辟的 buffer 里,此时我们就可以开始编辑这个文件了。注意,完成这一步动作需要调用外部的 iconv.dll(注2),你需要保证这个文件存在于 $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 的代码页)。

以下是我的 .vimrc 中关于字符编码方式设置的内容,这个设置比较有弹性,可以根据系统中的环境变量 $LANG(当然,Windows 中的写法是 %LANG%)的值来自动设置合适的字符编码方式。此时,推荐设置 %LANG% = zh_CN.UTF-8,可以通过后面的 Windows 注册表脚本文件来方便的做到。

" Multi-encoding setting, MUST BE IN THE BEGINNING OF .vimrc!

if has("multi_byte")
  " When 'fileencodings' starts with 'ucs-bom', don't do this manually
  " set bomb
  set fileencodings=ucs-bom,chinese,taiwan,japan,korea,utf-8,latin1
  " CJK environment detection and corresponding setting
  if v:lang =~ "^zh_CN"
    " Simplified Chinese, on Unix euc-cn, on MS-Windows cp936
    set encoding=chinese
    set termencoding=chinese
    if &fileencoding == ''
      set fileencoding=chinese
    endif
  elseif v:lang =~ "^zh_TW"
    " Traditional Chinese, on Unix euc-tw, on MS-Windows cp950
    set encoding=taiwan
    set termencoding=taiwan
    if &fileencoding == ''
      set fileencoding=taiwan
    endif
  elseif v:lang =~ "^ja_JP"
    " Japanese, on Unix euc-jp, on MS-Windows cp932
    set encoding=japan
    set termencoding=japan
    if &fileencoding == ''
      set fileencoding=japan
    endif
  elseif v:lang =~ "^ko"
    " Korean on Unix euc-kr, on MS-Windows cp949
    set encoding=korea
    set termencoding=korea
    if &fileencoding == ''
      set fileencoding=korea
    endif
  endif
   " Detect UTF-8 locale, and override CJK setting if needed
  if v:lang =~ "utf8$" || v:lang =~ "UTF-8$"
    set encoding=utf-8
  endif
else
  echoerr 'Sorry, this version of (g)Vim was not compiled with "multi_byte"'
endif

Windows 注册表脚本。

Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\\Environment]
"LANG"="zh_CN.UTF-8"

注1: 事实上,Vim 的探测准确度并不高,尤其是在 encoding 没有设置为 utf-8 时。因此强烈建议将 encoding 设置为 utf-8,虽然如果你想 Vim 显示中文菜单和提示消息的话这样会带来另一个小问题。参见另一篇 Win32 下 Vim 设置 enconding 为 utf-8 会在显示特定消息时崩溃。(此处提到的崩溃问题在 gVim 7.0 beta 时代就已经被解决了。)

注2: 在 GNU 的 FTP 上可以下载到 iconv 的 Win32 版,不推荐去 GnuWin32 下载 libiconv,因为那个版本旧一些,并且需要自己改名 dll 文件。

标签:, , ,

相关日志

9 Responses to “正确设置 Vim 的字符编码选项 (gVim/Vim on Win32 中文环境)”

  1. hjjhjjNo Gravatar Says:

    不错,locale改成utf8了,正需要设定呢

  2. 有鱼No Gravatar Says:

    由于空间提供商的服务器出了状况,我的wordpress不得以重新安装,但是非常不顺利,经过两天的折腾,还是没弄好。特来此地求助,希望能得到大侠的帮助

    情况是这样的,我用的都是原来正常时候的安装文件,wordpress(1.52),数据库也是原来建的那个。我记得我原来安装完成之后系统会发一封邮件到邮箱中告知用户名和密码,可是现在不会了,原来发表新文章也会发一封邮件到邮箱中,现在也不会了。还有就是在后台管理中,更改管理员密码时,非要填写icq号码才能更改,不然会出现如下出错信息:

    WordPress database error: [Out of range value adjusted for column ‘usericq’ at row 1] UPDATE wpusers SET userfirstname='’, userpass=MD5(’111111′), userlastname='’, usernickname=’Administrator’, usericq='’, useremail=’ajihua@gmail.com’, userurl=’http://’, useraim='’, usermsn='’, useryim='’, useridmode=’nickname’, userdescription = ‘’, user_nicename = ‘administrator’ WHERE ID = 1

    Warning: Cannot modify header information - headers already sent by (output started at E:\company\d\www\web\jxpx.com.cn\wp-includes\wp-db.php:98) in E:\company\d\www\web\jxpx.com.cn\wp-includes\pluggable-functions.php on line 127

    还有,不能编辑类别名称,我想把“未非类”这个类别更改名字,操作后出现如下错误信息:

    WordPress database error: [Out of range value adjusted for column ‘categoryparent’ at row 1] UPDATE wpcategories SET catname = ‘鏈垎’, categorynicename = ‘%e6%9c%aa%e5%88%86%e7%b1%bb’, categorydescription = ‘’, categoryparent = ‘’ WHERE cat_ID = ‘1′

    Warning: Cannot modify header information - headers already sent by (output started at E:\company\d\www\web\jxpx.com.cn\wp-includes\wp-db.php:98) in E:\company\d\www\web\jxpx.com.cn\wp-admin\categories.php on line 120

    还有,发表评论的时候也会出错,出错信息如下:

    WordPress database error: [Out of range value adjusted for column ‘userid’ at row 1] INSERT INTO wpcomments (commentpostID, commentauthor, commentauthoremail, commentauthorurl, commentauthorIP, commentdate, commentdategmt, commentcontent, commentapproved, commentagent, commenttype, user_id) VALUES (’3′, ‘wo’, ‘myulan@gmail.com’, ‘’, ‘218.66.48.151′, ‘2005-10-27 03:58:47′, ‘2005-10-27 03:58:47′, ‘鍝庡憖鍛€’, ‘0′, ‘Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Maxthon; .NET CLR 1.1.4322; Alexa Toolbar)’, ‘’, ‘’)

    Warning: Cannot modify header information - headers already sent by (output started at E:\company\d\www\web\jxpx.com.cn\wp-includes\wp-db.php:98) in E:\company\d\www\web\jxpx.com.cn\wp-comments-post.php on line 51

    Warning: Cannot modify header information - headers already sent by (output started at E:\company\d\www\web\jxpx.com.cn\wp-includes\wp-db.php:98) in E:\company\d\www\web\jxpx.com.cn\wp-comments-post.php on line 52

    Warning: Cannot modify header information - headers already sent by (output started at E:\company\d\www\web\jxpx.com.cn\wp-includes\wp-db.php:98) in E:\company\d\www\web\jxpx.com.cn\wp-comments-post.php on line 53

    Warning: Cannot modify header information - headers already sent by (output started at E:\company\d\www\web\jxpx.com.cn\wp-includes\wp-db.php:98) in E:\company\d\www\web\jxpx.com.cn\wp-comments-post.php on line 55

    Warning: Cannot modify header information - headers already sent by (output started at E:\company\d\www\web\jxpx.com.cn\wp-includes\wp-db.php:98) in E:\company\d\www\web\jxpx.com.cn\wp-comments-post.php on line 56

    Warning: Cannot modify header information - headers already sent by (output started at E:\company\d\www\web\jxpx.com.cn\wp-includes\wp-db.php:98) in E:\company\d\www\web\jxpx.com.cn\wp-comments-post.php on line 57

    Warning: Cannot modify header information - headers already sent by (output started at E:\company\d\www\web\jxpx.com.cn\wp-includes\wp-db.php:98) in E:\company\d\www\web\jxpx.com.cn\wp-comments-post.php on line 58

    Warning: Cannot modify header information - headers already sent by (output started at E:\company\d\www\web\jxpx.com.cn\wp-includes\wp-db.php:98) in E:\company\d\www\web\jxpx.com.cn\wp-includes\pluggable-functions.php on line 127

    其它好像都正常,可以新增类别,可以更改样式,也可以发表文章。

    初步判断是数据库错误,可是数据库链接应该正常,不然怎么可以安装和发表文章呢?各位达人,能帮我判断分析一下错误原因吗?在下将不胜感激!

  3. oiiNo Gravatar Says:

    seen

    签名:My Blog http://xiangtool.nease.net

  4. bywindNo Gravatar Says:

    感谢楼主的文章,让我解决了vim的问题。

  5. novaNo Gravatar Says:

    太有用了,在中文XP中工作完全正常,包括打开Notepad编辑的Unicode编码的文件,编辑中文,打印中文

    但在英文XP中还是有问题,汉字无法正确显示啊

  6. tooNo Gravatar Says:

    winxp 下设置 LANG=zh_CN.UTF-8 后,点任意文件后,右键菜单那个‘用vim 编辑’显示是乱码,只有把 LANG 这个设置去掉才能正常显示..... 有什么解决方法么?

  7. RainuxNo Gravatar Says:

    这个问题偶也苦恼了很久,前几天想到了解决办法但是没时间去做。

    方法是使用 OUTPUT_CHARSET 这个环境变量来设置 gvimext.dll 输出字符串所使用的字符编码 (设置为 GBK)。需要修改 gvimext.dll 的源代码。这个想法是从 Cygwin 里来的。如果楼上的朋友有时间,去 Vim 的 svn 上 co 一份 gvimext.dll 的源码来改了给 Bram 发个 patch 吧。:p

  8. Rainux's Weblog Says:

    解决 gvimext 在 UTF-8 locale 下乱码的问题...

    gvimext.dll 是一个为 Windows 里任意文件的右键菜单 (context menu) 添加“用 Vim 编辑”菜单项的 shell 扩展,随 gVim 一起安装。

    但是无论是官方的安装版本,还是我自己编译的版本,在使用 UTF-8 local...

  9. namespaceNo Gravatar Says:

    vista环境下怎么设定啊!好像中文是乱码

Leave a Reply