Windows中默认的文件格式是GBK(gb2312),而Linux 一般都是UTF-8。当文件中有中文字符时,在一个系统中能正常显示中文的,到另一个系统下常常会出现乱码。本文主要介绍两个系统下的编码转换解决中文乱码的问题。
乱码问题的由来
计算机内部是用"0"和"1"来表示信息的,那么如何用一串“0”和“1”来表示不同的字符呢,这就需要制定标准的编码方案,比如用“1000001”来代表字符“A”,用“110000”来代表字符“0”。这种编码标准化方案称为ASCII码,是美国在1961年提出的,并成为了国际标准。标准 ASCII 码使用 7 个二进位对字符进行编码,能表示常用的英文字母、数字、标点符号等。因此英文也成为了计算机世界的通用语言。
由于ASCII码只用了7 bit,所以ASCII码最多能表示128个字符,多出来的那一个bit位不是浪费了吗?不用担心,ISO标准化组织利用这最高位的bit位重新进行了字符编码,称为ISO-8859-1编码,最多能表示256个字符,前面0~127的字符编码跟ASCII码一样,保持兼容性,后面的128~255用来表示一些新的字符。Latin1是ISO-8859-1的别名,有些环境下也写作Latin-1,在很多协议上,默认使用该编码。
那么非英文国家的人怎么使用计算机表示非英文字符呢,这就跟某城市7位电话号码不够用就升8位类似,用更多位的二进制数来表示非英文字符,比如我们国家就用2个字节来对汉字进行编码,称为GB2312。
然而问题产生了,不同国家都用2个字节对本国语言进行编码,编码不通用,同一串二进制编码在不同国家代表不同的字符,真够乱的。为了解决非英文字符编码方案的统一问题,产生了Unicode。Unicode编码就像是一个翻译,每个语言自己的编码会一一对应到某个Unicode码,这样就把编码统一起来了,不管你说什么语言,用Unicode总归不会成乱码。为了统一编码,Unicode用4个字节来表示一个字符,从而导致编码效率非常低,让人无法忍受。
为了提高Unicode的编码效率,通过改进Unicode编码产生了UTF-8编码。UTF-8使用1-4个字节进行编码,可以根据不同的符号自动选择编码的长短,是目前使用范围最广泛的编码方案。
大致了解完了字符编码的历史问题,下面就来解决实际的乱码问题。
经常遇到乱码的场景
如果你像我一样以Linux作为主用的工作环境,那么在处理Windows下传过来的文件时,一般都是文本文件,肯定会经常遇到中文乱码的情况。
你在Linux下编辑的中文,保存为文件传到Windows下,对方打开也是乱码。
其实这都是因为不同的系统下默认字符编码不一致造成的,只需一条命令就能轻松搞定中文乱码。
在Linux中查看文件编码方式
1 在Vim中查看文件编码
用vim打开Windows传过来的文本文件,输入
:set fileencoding
返回结果:
fileencoding=latin1
这里Vim默认用latin1编码来识别文本字符,所以中文当然不能被latin1识别。
2 用enca命令识别文件编码
用法:
$ enca filename
返回结果:
Simplified Chinese National Standard; GB2312
CRLF line terminators
enca能正确识别出GB2312编码,不过enca对某些GBK编码的文件 识别的不是很好。
编码转换的几个方式
1 enconv 命令转换文件编码
例如,将一个GBK编码的文件转换成UTF-8编码:
enconv -L zh_CN -x UTF-8 inputfile
-L 表示从...编码
-x 表示转换到...编码
2 iconv 命令转换文件编码
例如,将一个UTF-8编码的文件转换成GBK编码:
iconv -f GBK -t UTF-8 inputfile > outputfile
-f 表示从...编码
-t 表示转换到...编码
iconv支持的编码类型比较多,我测试了一下iconv正反转换都没问题,但是enconv从utf-8转回GBK没有成功。一般建议用iconv来做编码转换,缺点是需要重定向到输出文件。
====iconv在手,乱码不愁====
网友评论