让VIM彻底告别乱码

转自:http://blog.csdn.net/smstong/article/details/51279810


1 字符编码基础知识

字符编码是计算机技术中最基本和最重要的知识之一。如果缺乏相关知识,请自行恶补之。这里仅做最简要的说明。

1.1 字符编码概述

所谓的字符编码,就是对人类发明的每一个文字进行数字化表示。最经典的ASCII编码就是西方人发明的针对英文字符的编码方法,包括26个英文字母、数字、标点、特殊字符等。问题是,这种编码的范围是0-127,只能对128个字符进行编码。当计算机来到其他国家后发现,除了英语,还有大量的其他语言,而且涵盖的字符也远远多于128个。为此,各个国家开始针对自己的语言进行编码工作,例如中国的GBK,日本的CJK,等等。

这虽然解决了ASCII编码不够用的问题,但是却带来了另外一个更加严重的问题。那就是各个国家的字符编码不统一,导致无法进行统一处理。于是乎,著名的UNICODE出现了,UNICODE编码范围非常大,可以涵盖全球所有语言的字符。

1.2 区分字符集(Charset)和字符编码(Char Encoding)

这两个术语有时候不进行区分的使用,但是理解其区别对于理解字符编码至关重要。

  • 代码点(Code Point)
    也就是我们前面说到的,为每一个字符分配一个数字序号。例如在ASCII字符集中,字符A被分配成65号,那就是说A的代码点是65。一种编码规范中,所有的代码点的集合就是字符集。

  • 字符编码
    字符编码是代码点的二进制存储格式。还是前面的例子,在ASCII字符集中,A的代码点是65。而这个65究竟是怎么用二进制0和1序列表示呢?这就是字符编码的工作。在ASCII编码中,这个65被存储为01000001,一共占据一个字节(8个二进制位)。

说到这里也许你会觉得,这中区别也没什么啊,这主要是因为在我们的例子中ASCII字符集的代码点只有一种字符编码方式,也就是ASCII字符编码。而这在其他字符集中却不总是这样,例如UNICODE字符集。

UNICODE字符集,规定了全球每一个字符的代码点,例如英文字母A在UNICODE字符集中的代码点是65(哈哈,这个代码点与ASCII是兼容的),然而65的存放格式却有很多方式:例如在UTF-8字符编码规范中被存储为8个二进制位:01000001,而在UCS-16中被存储为16个二进制位:0000000001000001,而在UCS-32中被存储为32个二进制位:00000000000000000000000001000001。

说到这里,就明白了,UNICODE字符集对应有很多不同的字符编码方式:UTF-8,UCS-16,UCS-32等等。
而ASCII字符集只有一种编码方式:ASCII字符编码。

UNICODE字符集的不同编码方式是为了适应不同的环境而被创造出来的,例如UTF-8被用来网络传输,文件存放,UCS-16则被用来作为内存中的存放方式,以利于快速统一计算。

现如今,虽然UNICODE字符集已经获得广泛采用,然而历史遗留的其他字符集仍大量存在。
近年来,字符集的概念很少被提及,字符编码则更多的被使用。

1.3 字符编码与显示

对字符进行编码只是完成了存放、处理和传输,要想把字符的形状绘制出来,还要有对应的字体以及渲染手段。

对于GUI程序,操作系统都会提供API来对指定字符进行渲染绘制。对于终端来说,终端有一个字符编码的属性,从而把接收到的二进制字节流按照这个字符编码进行解析,然后调用相应的渲染引擎来对其进行显示,详情请参考我的一篇博文:从调用printf()到显示器上看到字符串

2 VIM读取、显示、保存文本文件过程分析

2.1 VIM涉及到的字符编码

(1) 磁盘文件的字符编码
存放在磁盘上的文本文件,是按照一定的字符编码进行保存的,不同的文件可能使用了不同的字符编码。
这在VIM中被叫做:fileencoding。

(2) VIM缓冲区以及界面的字符编码
VIM运行时,其菜单、标签、以及各个缓冲区统一使用一种字符编码方式。
这在VIM中被叫做:encoding。

(3) 终端使用的字符编码
终端同一时刻只能使用一种字符编码,并按照这种编码从接收到的字节流中识别字符,并显示,终端的字符编码是可以动态调整的。
这在VIM中被叫做:termencoding。

2.2 vim读、显、存分析

(1)读文件
VIM打开文件时,并不知道文件的字符编码,所以不得不进行探测。探测是按照一定的优先顺序进行测试。依据的标准就是:fileencodings。VIM逐一测试fileencodings变量指定的字符编码方式,直到找到认为合适的然后把这种字符编码方式设置为fileencoding变量。

然后把文件中的编码转换成encoding指定的编码方式,存入文件缓冲区中。
(2)显示文件
vim把文件读取完毕并以encoding编码存放到缓冲区内存之后,会根据termencoding指定的终端编码方式,转换成termencoding编码后,写入到终端。此时,终端按照自身的编码属性识别出一个个的字符,调用渲染引擎绘制到屏幕上。

(3)保存文件
VIM把缓冲区中的encoding编码的字节集合转换成fileencoding编码后写入磁盘,完成文件保存。

可以看出,VIM涉及到的3种字符编码之间的转换:
读:fileencoding—–> encoding
显:encoding ——> termencoding
写:encoding ——-> fileencoding

只要这三种转换都不会出现问题,那么VIM就可以正常工作,不会出现乱码。
然而,并不是所有的字符编码之间都能够无损转换,例如GBK字符编码转换为ASCII编码时,由于ASCII并不能完全包含GBK的字符,所以会出现问题。

3 常见乱码情况分析

3.1 读文件时,VIM探测fileencoding不准确

这很好理解,比如以GBK编码方式存储的文件,VIM把fileencoding探测成了ASCII,则肯定会出现问题。

【解决方法】一是靠VIM自身提高探测水平;二是设置合适的fileencodings变量,把最可能用到的编码方式放到最前面。如果VIM实在是探测不对,那么就只能通过 :set fileencoding=xxx 命令来手动探测了。

3.2 fileencoding编码无法正确转换到encoding编码

例如,文件采用GBK编码,而ecoding使用ASCII,这样大量的汉字字符无法被转换,从而导致乱码。
【解决方法】把encoding设置成UTF-8,目前为止UTF-8能包含所有字符,所以其他的任何编码方式都可以无损的转换为UTF-8。

3.3 encoding无法正确转换到termencoding

这个问题,与3.2类似。
【解决办法】把termencoding设置为何encoding相同。默认termencoding=”“的情况下,这两者就是相同的。

3.3 termencoding与实际的终端字符编码不一致

例如本来字符终端的编码属性为GBK,而termencoding却为UTF-8,那么VIM就会错误的认为终端就是UTF-8编码的,导致向终端输出UTF-8编码的字节流,而终端却按照GBK来识别,当然就会识别成乱码。
【解决办法】把终端实际的编码方式和VIM的termencoding统一起来。

3.4 终端显示能力欠缺

例如,传统的字符终端,本身不具备显示汉字的能力,虽然它可以识别出UTF-8编码的汉字,但是渲染引擎无法正确绘制,也就显示成了乱码。
【解决办法】尽量还是使用Putty等伪终端软件,避免直接使用字符终端设备;如果实在不能避免,就要避免使用ASCII字符集以外的字符,好好学习英文吧。

4 杜绝乱码的最佳实践

所有编码统统设置为utf-8。这样既能够识别人类所有语言,又避免了各种编码之间转换的性能损失。

4.1 VIM设置

 
 
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3
set encoding=utf-8 set termencoding=utf-set fileencodings=utf-8,gbk,latin1

如果无特殊要求和限制,磁盘文件也以UTF-8方式存储。

  
  
  • 1
    • 1
    set fileencoding=utf-8

    4.2 终端设置

    常用的几种终端软件设置。
    (1)Putty

    (2)Mac Terminal

    版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

    相关推荐


    解决方案:解决linux下vim乱码的情况:(修改vimrc的内容)全局的情况下:即所有用户都能用这个配置文件地址:/etc/vimrc在文件中添加:setfileencodings=utf-8,ucs-bom,gb18030,gbk,gb2312,cp936settermencoding=utf-8setencoding=utf-8如果只修改个人的vim配置情况:需要把/etc/
    Linuxvi/vim所有的UnixLike系统都会内建vi文书编辑器,其他的文书编辑器则不一定会存在。但是目前我们使用比较多的是vim编辑器。vim具有程序编辑的能力,可以主动的以字体颜色辨别语法的正确性,方便程序设计。相关文章:史上最全Vim快捷键键位图—入门到进阶什么是vim
          vim正则匹配:空行:/^$/  /^[\t]*$/注释行:/^#/ /^[\t]*#/:1,$s/\([Rr]\)oot/\1ename/:1,$s/\(square\)and\(fair\)/\2and\1/ 
    $select-editorSelectaneditor.Tochangelater,run'select-editor'.1./bin/ed2./binano<----easiest3./usr/bin/code4./usr/bin/vim.basic5./usr/bin/vim.tinyChoose1-5[2]:4
    上次手贱忘了保存,这次就简单做个备忘吧,把踩过的坑记一下预览图安装工具:u盘、manjarokdeminimal20.0.3、win32DiskImager提取码:qt9f进bios、选择u盘启动、改语言、改时区、挂载分区(文件系统ext4、在200M左右的一个FAT分区上挂载/boot/efi)、安装安装很简单,按提示
    Linux之文本编译器小结vim的优势所有的UNIX-LIKE习通都会内置vi文本编译器,其他的文本编译器则不一定存在很多软件的编译接口都会主动调用vivim有很强的程序编译能力,可以主动的一字体颜色辨别语法的正确性,方便程序设计因为程序简单,编译速度相当快vi的使用一般命令模
    主机名字太长,怎么修改?  1.sudovim/etc/hostname 修改内容为wel,  本地主机名 2.sudovim/etc/hosts      修改主机名为wel,用于网络连接中主机名的识别 3.reboot 
    目录#事故现场#事故原因#解决方法方法一:使用notepad转换方法二:使用vscode转换方法三:使用vim转换#参考#事故现场执行shell脚本文件,报错::notfound.sh:6:coreinstall.sh:查看脚本文件第6行,发现是空行;#事故原因window下的换行是回车符+换行符,也就是\r\n,而unix下是换行符\n
    1、保存并退出linux下安装好了vim以及gcc后,我们开始新建一个c文件,例如:vimtest.c之后进入vim的编辑框中,点击i进入插入模式,开始编辑程序,当你编写好自己的程序之后,按Esc退出插入编辑状态,然后输入冒号加wq,点击Enter即可,完整的命令如下:wq如下图:  退出后,如果想要编译
    概述使用VIM作简单字数统计背景想做一个简单的字数统计环境OSwin10shellmintty-2.9.41.需求概述需求需求统计文段内字符的数量支持自定义字符集2.方案1:vim自带统计概述vim自带方案操作定位到文段内某行vi
    经典版下面这个键位图应该是大家最常看见的经典版了。对应的简体中文版其实经典版是一系列的入门教程键位图的组合结果,下面是不同编辑模式下的键位图。 
    ssh是一个安全连接协议。作用两个:1.远程连接协议,2.远程文件传输协议协议默认端口为:22。 修改默认端口,再到ssh服务配置文件位置  vim/etc/ssh/ssh_config这条命令就可以修改了。按下ESC键,再输入:x 也可以退出vim。(和:q! 相同)修改注意:1.端口号在0-65535之间。2.别人
    Vim是一个类似于Vi的著名的功能强大、高度可定制的文本编辑器,在Vi的基础上改进和增加了很多特性。VIM是自由软件。Vim普遍被推崇为类Vi编辑器中最好的一个,事实上真正的劲敌来自Emacs的不同变体。1999年Emacs被选为Linuxworld文本编辑分类的优胜者,Vim屈居第二。但在2000年2月Vim赢
    在Vim中,有时需要将tab转换成space。使用ret命令(replacetab)。[range]ret[ab]![new-tabstop]举例:将第一行到文件尾的tab转换成space,每个tab用4个space替代。:setexpandtab:%ret!4如果没有给定4,则用当前的tab宽度设定替换为space。 相关配置文件命令::settabstop=4设
    分屏命令记不得文件名就输入.可浏览文件命令英文功能:sp[文件名]split横向分屏:vsp[文件名]verticalsplit纵向分屏    切换分屏窗口先按Ctrlw切换窗口命令英文功能 wwindow切换下一个窗口 rreverse互换窗口 c
    1查看ctags支持的语言ctags--list-languages2查看语言和扩展名的对应关系ctags--list-maps 3对当前目录下所有ctags支持的语言格式文件生成tagsctags-R*缺点很明显,tags会非常大,tags生成会非常慢,而且代码跳转会卡顿。4只对特定文件生成tagsctags`find-name"*.h"`ct
    vim基本命令 $vimtutor可以查看基本的vim操作1h(left)j(down)k(up)l(right)q!wqi:insertbeforethecursor(insert)插队嘛,肯定在光标前面A:appendaftertheline(appending)2dw:删除一个单词,保留光标前面部分d$:删除光标之后的同行
    ~/.vimrc内容如下:setnocompatiblefiletypeoffsetrtp+=~/.vim/bundle/Vundle.vimcallvundle#begin()Plugin'VundleVim/Vundle.vim'Plugin'tpope/vim-fugitive'Plugin'tpope/vim-unimpaired'Plugin'tpope/vim-repeat'Plu
    程序:硬盘静态的代码  占用磁盘空间进程:内存运行计算的代码 占用CPU运行内存父进程与子进程  树型结构进程唯一标识: PID僵尸进程找到父进程杀掉  孤儿进程疯狂要内存  危害大 pstree [选项]-a显示完整命令行   -p 查看PID [PID或用户
    ~/.vimrc"Configurationfileforvimsetmodelines=0 "CVE-2007-2438setnumber"setrelativenumber"显示相对行号(这个非常重要,慢慢体会)setcursorlinesetcursorcolumnsetrulersetscrollbindsetencoding=utf-8colormolokaisyntaxon"开启