Ruby实例编程说明字符编码,解决乱码问题
Posted 虫虫搜奇
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Ruby实例编程说明字符编码,解决乱码问题相关的知识,希望对你有一定的参考价值。
日常编码中,你是不是常见到乱码问题,那么乱码是怎么来的呢,今天虫虫就以Ruby为例来,说明字符编码、底层的字节码以及各种字符编码转化,最后说下怎么解决乱码问题。
我们以一个Ruby抛出的错误异常为开头,某年某月某日,你正用irb学习Ruby突然屏幕上抛出了一个异常:
Encoding::InvalidByteSequenceError: "\xFE" on UTF-8
或者 "they're"被显示为"they’re"。
所以,当出现编码错误,或者乱码时候,我们怎么排查问题出在哪里?如何解决它?
什么是编码?
如果你了解字符串以及编码之间的关系,其实这些问题很容易解决。
我们可以将字符串视为字节数组或数字:
2.1.4 :002 > "chongchong!".bytes
=> [99, 104, 111, 110, 103, 99, 104, 111, 110, 103, 33]
在这种编码中,99表示c,104表示h,…,33表示!。
当你使用英语中不常见的字符时,情况会变得更加复杂:
2.1.4 :007 > "chongchong".bytes
=> [240, 159, 166, 139, 99, 104, 111, 110, 103, 99, 104, 111, 110, 103]
现在很难判断哪个数字代表哪个字符了把。这个蝴蝶字符使用一组字节[240, 159, 166, 139]表示,而不是一个字节。但字节和符号之间会存在着一定的对应关系。这种定义字节和符号(字符串)之间的对应关系,我们叫编码。
不同编码转换
在不同编码环境下,一个字节可能呈现出不同的符号表现:
2.1.4 :021 > str = "虫虫,秊﨟蘒!".encode("GBK");
2.1.4 :022 > str.encode("UTF-8")
=> "虫虫,秊﨟蘒!"
2.1.4 :027 > str.bytes
=> [179, 230, 179, 230, 163, 172, 253, 158, 254, 72, 254, 73, 33]
GBK的字串,我们看看在西文编码的ISO-8859-5下会是怎么显示呢?
str.force_encoding("ISO-8859-5"); str.encode("UTF-8")
2.1.4 :003 > str.force_encoding("ISO-8859-5"); str.encode("UTF-8")
=> "ГцГцЃЌ§\u009EўHўI!"
2.1.4 :004 > str.bytes
=> [179, 230, 179, 230, 163, 172, 253, 158, 254, 72, 254, 73, 33]
我们可以看到,字节码没有变化,但是看起来乱码了。改变编码会改变字符的显示方式,但是不会改变字节码,不同的编码,有不同的字节码解析方式。
从GB2312到GBK,选择UTF8
另外我们需要注意的是,每一种编码的数量都有限量,有些编码数量少,会导致其他编码转过来会不支持,比如GBK是GB2312的扩展集合支持21886个字符,而GB2312只支持7445个字符。注意UTF8和UTF16是全字符集,支持所有编码的字符,这就是为什么建议大家写代码一定都用UTF8的原因,当然在Windows下微软屎一样的,坚持自己要带UTF8 BOM,还不能方便的转换,所以也很讨厌。
2.1.4 :005 > str.force_encoding("GB2312"); str.encode("UTF-8")
Encoding::InvalidByteSequenceError: "\xFD" followed by "\x9E" on GB2312
from (irb):5:in `encode'
from (irb):5
from /home/lz/.rvm/rubies/ruby-2.1.4/bin/irb:11:in `<main>'
后面那三个字,在GB2312下没有编码,所以报错了。
我们将编码修改为GB18030,这是一种比GBK更大的中文字符集,显示就没问题了。
我们也可以给encode函数添加invalid和undef两个参数,这样当无法解释时候会用默认的?来代替,就不会报错了。
"chongchong,秊﨟蘒!".encode("GB2312", invalid: :replace, undef: : replace)
=> "chongchong\x{A3AC}???!"
我们常见的编码问题有两种现象,一种是编码不对,就是完全乱码,乱显示随机字符,还有一种就编码不足以解析字符集会有很多的??的。
当你对字符转换编码时,很多时候,你不能获得足够的信息,你不知道究竟是哪一个被替换成了?但是你起码知道选的编码没有错,只不过不足以显示所有字符而已,你换一种字符集更多的编码就正常了。比如GB2312->GBK-> GB18030
总结
在文章中,我们目前用到了三个字符串对象方法来帮我们处理编码问题:
ecode,将字符串转换为另一种编码(在新编码中将字符转换为相应字符)
bytes,它将显示组成字符串的字节码(整数数组)
force_encoding,强制将一种编码转换为一种编码,用这宗编码来重新解析内容。
其实上编码问题在各种语言都存在,这儿虫虫选择了Ruby中三个类方法来作为实例演示,其他语言中也有类似的方法和函数,比如:
golang中的golang.org/x/text/encoding/simplifiedchinese包。
python中的enode()和decode(),XX_name(XX为编码)方法。
Perl中encode包中也有enode()和decode()。
Java中有getBytes(),charset类有enode()和decode()方法。
以上是关于Ruby实例编程说明字符编码,解决乱码问题的主要内容,如果未能解决你的问题,请参考以下文章