DDR爱好者之家 Design By 杰米

因为电脑是windows 7系统,开发环境又在linux,经常在linux碰到乱码问题,很是痛苦,于是决定好好了解编码的来龙气脉,并分享个各位,免得出现乱码时不知所措。

是否存在文件编码

在讲解字符编码之前,我们需先明确文件本身没有编码一说,只有文字才有编码的概念,我们通常说某个文件是什么编码,通常是指文件里字符的编码。

vim为什么会出现乱码

我在linux下一般使用vim进行文件编辑,发现经常会碰到乱码的情况,那么为什么会出现乱码呢? 首先我们了解下vim编码方面的基础知识,关于编码方面vim存在3个变量:

1.encoding: Vim 内部使用的字符编码方式,包括 Vim 的 buffer (缓冲区)、菜单文本、消息文本等。默认是根据你的locale选择.用户手册上建议只在 .vimrc 中改变它的值,事实上似乎也只有在.vimrc 中改变它的值才有意义。你可以用另外一种编码来编辑和保存文件,如你的vim的encoding为utf-8,所编辑的文件采用cp936编码,vim会自动将读入的文件转成utf-8(vim的能读懂的方式),而当你写入文件时,又会自动转回成cp936(文件的保存编码).

2.fileencoding: Vim 中当前编辑的文件的字符编码方式,Vim 保存文件时也会将文件保存为这种字符编码方式 (不管是否新文件都如此)。

3.termencoding: Vim 所工作的终端 (或者 Windows 的 Console 窗口) 的字符编码方式。如果vim所在的term与vim编码相同,则无需设置。如其不然,你可以用vim的termencoding选项将自动转换成term的编码.

当这三个变量的编码出现问题时就会出现乱码:

1.encoding不是utf-8编码:如果encoding不是utf-8编码,其他字符可能无法转为 Encoding的指定编码。如:如果encoding是gbk编码,而文件内容采用big5编码的,其就无法转换为gbk编码。

2.fileencoding不对:Fileencoding编码是vim的读取文件内容时使用的编码,如果其编码与文件字符编码不同,必然会出现乱码。Fileencoding编码一般由vim自动检测,可以使用fileencodings设置,Vim自动探测fileencoding的顺序列表。不过vim有时候会检测错误,就会出现乱码了。

3.termencoding编码不对:我们登录服务器一般采用远程登录,这就涉及终端编码问题,我经常碰到因为终端编码不对导致乱码的。如:SecureCRT设置为utf-8编码,而vim的termencoding却为gbk,就出现乱码了。

字符编码介绍

说了那么多,到底字符编码是什么玩意呢?

字符(Character)是文字与符号的总称,包括文字、图形符号、数学符号等,一组抽象字符的集合就是字符集(Charset)。 字符集常常和一种具体的语言文字对应起来,该文字中的所有字符或者大部分常用字符就构成了该文字的字符集,比如英文字符集,汉字字符集。 计算机要处理各种字符,就需要将字符和二进制内码对应起来,这种对应关系就是字符编码(Encoding)。 制定编码首先要确定字符集,并将字符集内的字符排序,然后和二进制数字对应起来。根据字符集内字符的多少,会确定用几个字节来编码。

字符集和编码的区别:

字符集字符的集合,不一定适合计算机存储、网络传送、处理,有时须经编码(encode)后才能应用。如Unicode字符集可依不同需要以UTF-8、UTF-16、UTF-32等方式编码。

字符编码的发展

字符编码大概分为三个发展阶段。

ASCII编码:ASCII(American Standard Code for Information Interchange,美国信息互换标准代码)是基于拉丁字母的一套电脑编码系统。 因为计算机起源于美国,为表示英文字符,他们制定了ASCII编码,ASCII编码使用7位二进制来表示字符,高位用来做奇偶校验,0×20以下的字节状态称为”控制码”,同时包括标点符号、数字等,当时人们觉得已经够用了。

多种编码并存:但随着计算机的广泛应用,别的国家也开始使用计算机,但是很多国家用的不是英文,他们的字母里有许多是ASCII里没有的,为了可以在计算机保存他们的文字,他们决定采用127号之后的空位来表示这些新的字母、符号,还加入了很多画表格时需要用下到的横线、竖线、交叉等形状,一直把序号编到了最后一个状态255。从128到255这一页的字符集被称”扩展字符集”。最优秀的扩展方案是ISO 8859-1,通常称之为Latin-1,Latin-1包括了足够的附加字符集来写基本的西欧语言。

后来其他国家也开始使用计算机,为了表达自己国家的文字,不同的国家和地区制定了不同的标准,产生了GB2312,BIG5,JIS等各自的编码标准。通常使用0×80~xFF范围的2个字节来表示1个字符。比如:汉字 ‘中' 在中文操作系统中,使用 [0xD6,0xD0]这两个字节存储。 这些使用2个字节来代表一个字符的延伸编码方式,称为 ANSI 编码。

在简体中文系统下,ANSI 编码代表 GB2312 编码,在日文操作系统下,ANSI 编码代表 JIS 编码。 不同 ANSI 编码之间互不兼容,当信息在国际间交流时,无法将属于两种语言的文字,存储在同一段 ANSI 编码的文本中。

Unicode编码 由于不同国家的ANSI编码互不兼容,为了使国际间信息交流更加方便,国际组织制定了UNICODE字符集,为各种语言中的每一个字符设定了统一并且唯一的数字编号,以满足跨语言、跨平台进行文本转换、处理的要求。 UNICODE开始制订时,计算机的存储器容量极大地发展了,空间再也不成为问题了。于是ISO就直接规定必须用两个字节,也就是16位来统一表示所有的字符,对于ascii里的那些“半角”字符,UNICODE保持其原编码不变,只是将其长度由原来的8位扩展为16位,而其他文化和语言的字符则全部重新统一编码。由于”半角”英文符号只需要用到低8位,所以其高8位永远是0,因此这种大气的方案在保存英文文本时会多浪费一倍的空间。

但是UNICODE来到时,一起到来的还有计算机网络的兴起,UNICODE如何在网络上传输也是一个必须考虑的问题,于是面向传输的众UTF(UCS Transfer Format)标准出现了,顾名思义,UTF8就是每次8个位传输数据,而UTF16就是每次16个位,只不过为了传输时的可靠性,从UNICODE到UTF时并不是直接的对应,而是要过一些算法和规则来转换。

学过计算机网络的童鞋都知道,在网络里传递信息时有一个很重要的问题,就是对于数据高低位的解读方式,一些计算机是采用低位先发送的方法,例如我们PC机采用的INTEL架构;而另一些是采用高位先发送的方式。在网络中交换数据时,为了核对双方对于高低位的认识是否是一致的,采用了一种很简便的方法,就是在文本流的开始时向对方发送一个标志符——如果之后的文本是高位先发送,那就发送”FEFF”,反之,则发送”FFFE”。(IP/TCP协议规定网络字节序使用大端法)
因为UTF-8编码兼容之前的ASCII编码,而且有利于传输,其得到了非常广泛的应用。

从UNICODE到UTF8的转换规则:

复制代码 代码如下:
Unicode             UTF-8
0000 - 007F         0xxxxxxx
0080 - 07FF         110xxxxx 10xxxxxx
0800 - FFFF         1110xxxx 10xxxxxx 10xxxxxx

汉字ANSI编码发展

GB2312:为了表示汉字,我们国家首先发明了GB2312 编码,GB2312 编码规定一个小于127的字符的意义与原来相同,但两个大于127的字符连在一起时,就表示一个汉字,前面的一个字节(他称之为高字节)从0xA1用到0xF7,后面一个字节(低字节)从0xA1到0xFE,这样我们就可以组合出大约7000多个简体汉字了。在这些编码里,我们还把数学符号、罗马希腊的字母、日文的假名们都编进去了,连在 ASCII 里本来就有的数字、标点、字母都统统重新编了两个字节长的编码,这就是常说的”全角”字符,而原来在127号以下的那些就叫”半角”字符了。

GBK 后来发现很多偏僻字和少数名族的语言还是没办法编码进来,为了表示这些字符,于是干脆不再要求低字节一定是127号之后的内码,只要第一个字节是大于127就固定表示这是一个汉字的开始,不管后面跟的是不是扩展字符集里的内容。结果扩展之后的编码方案被称为 GBK 标准,GBK包括了GB2312的所有内容,同时又增加了近20000个新的汉字(包括繁体字)和符号。

GB18030 后来少数民族也要用电脑了,于是我们再扩展,又加了几千个新的少数民族的字,GBK扩成了GB18030。从此之后,中华民族的文化就可以在计算机时代中传承了。

BOM介绍

1.BOM的来历: 为了识别 Unicode 文件,Microsoft 建议所有的 Unicode 文件应该以 ZERO WIDTH NOBREAK SPACE(U+FEFF)字符开头。这作为一个“特征符”或“字节顺序标记(byte-order mark,BOM)”来识别文件中使用的编码和字节顺序。

2.不同的系统对BOM的支持:因为一些系统或程序不支持BOM,因此带有BOM的Unicode文件有时会带来一些问题。

①JDK1.5以及之前的Reader都不能处理带有BOM的UTF-8编码的文件,解析这种格式的xml文件时,会抛出异常:Content is not allowed in prolog。
②Linux/UNIX 并没有使用 BOM,因为它会破坏现有的 ASCII 文件的语法约定。
③不同的编辑工具对BOM的处理也各不相同。使用Windows自带的记事本将文件保存为UTF-8编码的时候,记事本会自动在文件开头插入BOM(虽然BOM对UTF-8来说并不是必须的)。而其它很多编辑器用不用BOM是可以选择的。UTF-8、UTF-16都是如此。

3.BOM与XML:XML解析读取XML文档时,W3C定义了3条规则:

①如果文档中有BOM,就定义了文件编码;
②如果文档中没有BOM,就查看XML声明中的编码属性;
③如果上述两者都没有,就假定XML文档采用UTF-8编码。

决定文本的字符集与编码

软件通常有三种途径来决定文本的字符集和编码:

1.检测BOM

对于Unicode文本最标准的途径是检测文本最开头的几个字节。   
复制代码 代码如下:
    开头字节        Charset/encoding
    EF BB BF        UTF-8
    FE FF           UTF-16/UCS-2, little endian(UTF-16LE)
    FF FE           UTF-16/UCS-2, big endian(UTF-16BE)
    FF FE 00 00     UTF-32/UCS-4, little endian.
    00 00 FE FF     UTF-32/UCS-4, big-endia

2.用户选择: 采取一种比较安全的方式来决定字符集及其编码,那就是弹出一个对话框来请示用户。

3.采取“猜”的方法: 如果软件不想麻烦用户,或者它不方便向用户请示,那它只能采取自己“猜”的方法,软件可以根据整个文本的特征来猜测它可能属于哪个charset,这就很可能不准了。使用记事本打开那个“联通”文件就属于这种情况。(把原本属于ANSI编码的文件当成UTF-8处理。

记事本的几种编码介绍

1.ANSI编码:记事本默认保存的编码格式是:ANSI,即本地操作系统默认的内码,简体中文一般为GB2312。这个怎么验证呢?用记事本保存后,使用EmEditor、EditPlus和UltraEdit之类的文本编辑器打开。推荐使用EmEditor,打开后,在又下角会显示编码:GB2312。

2.Unicode编码:用记事本另存为时,编码选择“Unicode”,用EmEditor打开该文件,发现编码格式是:UTF-16LE+BOM(有签名)。用十六进制方式查看,发现开头两字节为:FF FE。这就是BOM。

3.Unicode big endian 用记事本另存为时,编码选择“Unicode”,用EmEditor打开该文件,发现编码格式是:UTF-16BE+BOM(有签名)。用十六进制方式查看,发现开头两字节为:FE FF。这就是BOM。

4.UTF-8 :用记事本另存为时,编码选择“UTF-8”,用EmEditor打开该文件,发现编码格式是:UTF-8(有签名)。用十六进制方式查看,发现开头三个字节为:EF BB BF。这就是BOM。

DDR爱好者之家 Design By 杰米
广告合作:本站广告合作请联系QQ:858582 申请时备注:广告合作(否则不回)
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
DDR爱好者之家 Design By 杰米

稳了!魔兽国服回归的3条重磅消息!官宣时间再确认!

昨天有一位朋友在大神群里分享,自己亚服账号被封号之后居然弹出了国服的封号信息对话框。

这里面让他访问的是一个国服的战网网址,com.cn和后面的zh都非常明白地表明这就是国服战网。

而他在复制这个网址并且进行登录之后,确实是网易的网址,也就是我们熟悉的停服之后国服发布的暴雪游戏产品运营到期开放退款的说明。这是一件比较奇怪的事情,因为以前都没有出现这样的情况,现在突然提示跳转到国服战网的网址,是不是说明了简体中文客户端已经开始进行更新了呢?