2009年九月月 发布的文章

也谈VIM字符集编码设置

安装完中文语言包支持后,Ubuntu的默认locale是zh_CN.UTF-8(即简体中文语言环境,字符集内码UTF-8)。这与我们日常开发环境中Unix设定的环境有所区别,我们日常使用的环境一般为zh_CN.GBK或zh。我们的源代码文件的字符编码也都是GBK的编码,直接在Ubuntu下用默认设置的VIM打开后,中文的注释会显示乱码。如果你直接编辑这个文件并提交,那么其他在Unix下开发的同事Checkout这份源码后打开也将显示乱码(你新增的中文内容会是乱码)。

解决这个问题至少有两种方法:一种是为Ubuntu新增加一个zh_CN.GBK的locale的支持,内码使用GBK;另外一种就是通过设置VIM,在不变换Ubuntu所支持的locale(内码依旧是UTF-8)的情况下支持对GBK内码文件的读写。

第一种方法简单说一下,总共分四步走:
第一步:sudo vi /var/lib/locales/supported.d/local,该文件原始状态只有一行记录:zh_CN.UTF-8 UTF-8;为了增加zh_CN.GBK的locale,我们在这个文件尾添加一行:zh_CN.GBK GBK,保存退出。

第二步:执行:sudo locale-gen,生成zh_CN.GBK对应的locale
第三步:编辑:/etc/environment,在文件尾添加如下内容:
LANGUAGE="zh_CN:zh:en_US:en"
LANG=zh_CN.GBK
LC_CTYLE=zh_CN.GBK
LC_ALL="zh_CN.GBK"

第四步:重启Ubuntu系统。重启后用VIM再打开以前GBK编码的源代码文件,就不再会有乱码了,而且默认情况下编辑文件采用的依然是GBK编码。不会影响他人在其他平台上读写文件。

第二种方法是本文重点要谈的内容。即在zh_CN.UTF-8的环境下保证正确读写GBK编码的文件。问题主要集中在:如何读出并正确显示已有的特定字符编码的文件和如何按照特定字符编码写新文件。

这里有两个数据文件:data1和data2,内容都是“祝祖国六十年生日快乐”,但是data1采用UTF-8编码,而data2采用GBK编码,可以用od -x查看文件实际存储数据是不同的。
od -x data1
0000000 a5e7 e79d 96a5 9be5 e5bd ad85 8de5 e581
0000020 b4b9 94e7 e69f a597 bfe5 e4ab 90b9 000a
0000037

od -x data2
0000000 a3d7 e6d7 fab9 f9c1 aeca eac4 fac9 d5c8
0000020 ecbf d6c0 000a
0000025

在终端UTF-8编码,LC_ALL=zh_CN.UTF-8,VIM默认配置的前提下,尝试用VIM分别打开data1和data2,发现data1正常显示,data2显示乱码;为什么呢?这里VIM当打开一个已存在的文件时会有一系列的处理过程:

用VIM打开一个已存在的文件时,VIM首先要查看fileencodings(或fencs)这个option。fileencodings是一系列字符编码格式的列表,例如:set fileencodings=GBK,UTF-8,gb18030,ucs-bom,cp936。这个option仅在打开一个已存在的文件时起作用。如果你没有在.vimrc中显式set这个option,那fileencodings的默认值是'ucs-bom,UTF-8,default,latin1',其中default的值是用户环境的默认编码格式。

当你打开一个已存在的文件时,VIM会用fileencodings值列表中的编码格式逐一去探测该文件的编码方式,直到两者匹配一致。探测成功后,VIM会用匹配到的编码格式去设置此文件session的fileencoding选项值。fileencoding选项指示该session的VIM BUFFER里的数据写入文件或从文件读出时文件中的数据的编码格式。同样该session中VIM BUFFER中数据的编码格式则由另外一个选项指示,那就是encoding option。这里有多个"encoding-like"字样的options,极易混淆。但实际上真正对VIM文件操作时数据显示和保存起作用的只有两个选项:fileencoding和encoding。而fileencodings只是在打开已有文件时用来探测并设置fileencoding字段的一个外围option。VIM的编码转换也是围绕fileencoding和encoding这两个options展开的。无论读写文件,当某个VIM session中fileencoding和encoding的值不一致时,VIM就会自动做编码转换。例如:当读取一个文件时,session的fileencoding为UTF-8,而encoding为GBK时,VIM将文件中的数据读出来后会自动做一个UTF-8到GBK的转换,并将转换后的数据存储在VIM针对该session的BUFFER里;同样当创建一个新文件时,如果该session的vim BUFFER中数据的编码格式(encoding指示)和fileencoding指示的文件编码格式不一致时,save file时,VIM会自动将BUFFER中的数据按照fileencoding指示的编码格式进行一次转换后再存入新文件中。

每个option都有三种状态:显式设置、空(encoding除外)和默认值。其中显式设置是指在.vimrc或在session中利用set指令对选项进行赋值设置;空:比较特殊,表示该选项的值为empty;默认值则是未通过set在.vimrc或在session对选项进行赋值的状态。

fileencodings为空时,即在.vimrc中set fileencodings="";VIM将无法进行文件编码探测,将直接根据fileenoding和encoding的值来确定文件编码和BUFFER编码以及是否需要自动做编码转换;当fileencodings不为空,但探测文件编码均告失败时,VIM会将该session的fileencoding置为空,之后将根据encoding的值来设置文件编码和VIM BUFFER编码。

fileencoding的默认值就是空(""),打开已有文件时通过fileencodings来设置其值,新建文件时如果fileencoding为默认值或空,那么encoding将决定一切。其显式设置的值只有在新建文件的session中才会其作用。

encoding是核心,是VIM session中BUFFER数据的编码,也可以理解为VIM核心的内码;VIM会根据它与fileencoding、termencoding(term的编码格式)的不同由VIM做自动转码。encoding默认值为$LANG。

下面用一些例子来说明一下VIM的行为模式,测试环境Ubuntu 9.04, LANG=zh_CN.UTF-8, data1和data2如上所述。
(1) 三个Option均采用默认值,没有在.vimrc下显式设置
此时在vim session未建立之前,fileencodings的默认值为“ucs-bom,UTF-8,default,latin1”,fileencoding为空,encoding=UTF-8($LANG).打开data1,VIM通过fileencodings做探测,顺利匹配到UTF-8的编码格式,将fileencoding设置为UTF-8,此时encoding也为UTF-8,两者一致,VIM不做编码转换,屏幕正确显示“祝祖国六十年生日快乐”。打开data2,VIM通过fileencodings做探测,未能匹配到GBK的编码,将fileencoding置为空,encoding发挥作用,VIM不做任何编码转换,将GBK编码的数据以UTF-8格式显示,屏幕显示乱码。

(2) fileencodings显式被设置为"UTF-8,GBK",其他option采用默认值
此时在vim session未建立之前,fileencodings的值为“UTF-8,GBK”,fileencoding为空,encoding=UTF-8($LANG).打开data1,VIM通过fileencodings做探测,顺利匹配到UTF-8的编码格式,将fileencoding设置为UTF-8,此时encoding也为UTF-8,两者一致,VIM不做编码转换,屏幕正确显示“祝祖国六十年生日快乐”。打开data2,VIM通过fileencodings做探测,顺利匹配到GBK的编码,将fileencoding置为GBK,此时encoding为UTF-8,两者不一致,VIM做自动编码转换,将GBK编码的数据转换为UTF-8格式后放入BUFFER并显示,屏幕正确显示“祝祖国六十年生日快乐”,VIM在状态条提示“已转换”。

(3) fileencoding显式设置为"GBK",encoding显式设置为“UTF-8”或采用默认值
新建一个文件data3,输入:“祝祖国六十年生日快乐”,保存,此时fileencoding和encoding值不一致,VIM做自动编码转换,将BUFFER中的UTF-8编码的数据转换为GBK编码后存储到文件中,VIM状态栏提示“已转换”。退出VIM。od -x data3,输出的是GBK编码。

“找回”自己的密码

继续昨天的情况道来。话说昨天因瞬时“失忆”,导致将公司办公账户的密码忘记了。这给工作带来的不便是我没有想到的。今天一上班就询问秘书密码重置的进度,得到的回复是已经发给公司HR并催促多次了。但是直到近中午也未曾收到密码重置的通知,耐不住性子的我终于决定亲自跟踪这件事,电话直接打到HR部门负责此事的专员那,结果无人接听,一连多次,估计是那个同事不在Office。遂直接拨打公司IT服务部门的电话,说明了情况,这个部门的态度倒是很好,帮我查了一下,并告知我昨天没有收到HR那边的邮件,并答应我,一旦收到邮件就会马上处理的。

放下电话又想了想,觉得我不能就这么等下去,应该尝试一下找回自己的密码。虽然昨天瞬时“失忆”,但是自己的密码组成规则还是记得的。公司的密码起码的要求包括长度、大小写字母和特殊符号。记得当时我只是想换一下大写字母的位置,只是事后忘记了调整了哪两个字母。午饭过后,决定花一定时间尝试去“找回”自己的密码,工具吗,用Ruby+Watir。用Watir来操作IE,用穷举的方法来尝试各种密码组合,直到能正确登录的密码就是我想要的。Watir好久没有用了,而且也没有现成的包,还得重新安装,Ubuntu上安装Watir总是提示已存在的文件的gem格式不符,无奈回到Windows上安装。先用C代码生成了所有可能的密码组合,写到一个文件中,每行一个密码。然后在网上找到了Watir使用的例子,参考之完成了自己的脚本:打开公司内外首页,用文件中的密码逐一尝试,如果登录成功,则脚本执行结束。

一杯咖啡功夫,脚本执行完了,不过出乎意料的是没有一个密码是正确的,这让我大为疑惑。30分钟后,Ubuntu上的iptux闪动,秘书将重置后的密码发了过来,我再一想估计是在我尝试“破解”之前IT服务部门的同事就已经将密码重置了,所以我穷举的那些密码也就都不正确了。

现在我最想知道的就是到底我昨天更改后的密码是什么^_^。

瞬时“失忆”,密码忘记

密码这东西在信息化的今天真是很重要,估计大家一张口就能说出5个以上使用密码的地方:登录网银、上淘宝、上亚马逊购书、写博客、登录Gmail等等。平时在公司,我的mail就是我的ID,公司所有内部网络服务都需要使用这个ID登录,甚至包括内部无线网络也是如此,所以在公司办公,内部mail账户和密码很重要。

公司为了加强信息安全管理,要求每位员工的密码都要符合SOX规范,而且要每隔若干个月就要对密码做一次修改,更有甚者公司内网首页居然做了强制密码修改的校验,如果你超出规定时间没有修改密码,那么当你登录公司内网时就必须修改密码,否则就无法登入。

今天就因为这个让我“损失”大了。符合SOX规范的密码较长也比较难记,所以大家也都总偷懒,很少去改密码。今天为了到内网去下载一个文档,不得不被强制修改密码。修改密码时有些三心二意了,改完后,突然感觉“瞬时”失忆了似的,刚才的新密码就是想不起来了,试了十几次,仍然无法想起正确的密码。这下可惨了,一分钟后,无线网络断了、outlook和thunderbird相继弹出输入密码对话框、Firefox也弹出了输入代理密码的对话框。无奈只能向秘书“求救”,后被告知重置密码还真不那么简单,先要秘书发mail给人力,人力再发mail给公司网络管理部门,之后如何处理还不得而知了。不过公司的办事效率也真不怎么高,到现在为止我仍然没能恢复我的密码,真是耽误事啊。一天了都没能收到mail,中间有几封重要的客户mail也没能及时回复。

悔啊!




这里是Tony Bai的个人Blog,欢迎访问、订阅和留言!订阅Feed请点击上面图片

如果您觉得这里的文章对您有帮助,请扫描上方二维码进行捐赠,加油后的Tony Bai将会为您呈现更多精彩的文章,谢谢!

如果您喜欢通过微信App浏览本站内容,可以扫描下方二维码,订阅本站官方微信订阅号“iamtonybai”;点击二维码,可直达本人官方微博主页^_^:



本站Powered by Digital Ocean VPS。

选择Digital Ocean VPS主机,即可获得10美元现金充值,可免费使用两个月哟!

著名主机提供商Linode 10$优惠码:linode10,在这里注册即可免费获得。

阿里云推荐码:1WFZ0V立享9折!

View Tony Bai's profile on LinkedIn


文章

评论

  • 正在加载...

分类

标签

归档











更多