Ruby字符串的编码

12月 21st, 2014 5,730 留下评论 阅读评论

相比较于Java String的编码转换(先将String根据原字符集转化为字节数组,然后再用字节数组根据新字符集拼装成新的字符串),Ruby的字符串编码转化省去了中间字节数组的过程,直接string.encode(new_encoding)即可。

字符串与字节串

Ruby的字符串存储的都是字节,还有一个编码,根据这个编码对应的字符集来渲染字符。可以通过如下清除字符串的编码信息还原为裸的字节串:

str = '中'   #GBK编码
s1 = [str].pack('a*')   =>   "\xD6\xD0"

str = '中'.encode('UTF-8')    #转化为UTF-8编码
s2 = [str].pack('a*')   =>   "\xE4\xB8\xAD"

#Array.pack('a*')是用来向ASCII字符串结尾加入\0用的,所以会清除其他字符串的编码信息

s1.encoding.name => "ASCII-8BIT"

现在得到的s1和s2字符串都是ASCII-8BIT的编码(或者说是没有带字符集的裸字节字符串),只要加上一个编码信息,就可以还原为GBK或者UTF-8的字符串,这种方式和Java也比较像了吧。

s1.force_encoding('GBK')          =>     '中'
s2.force_encoding('UTF-8')         =>     '中'

Ruby中的字节数组,官方并没有给String直接的一个API来获取,但可以用过str.unpack('c*') 或者str.unpack('C*')来获取,前者带符号位,后者不带符号位。

str = '中'   #GBK编码
[str].pack('c*')   =>   [-42, -48]                  [str].pack('C*')   =>  [214, 208]

str = '中'.encode('UTF-8')    #转化为UTF-8编码
[str].pack('c*')   =>  [-28, -72, -83]              [str].pack('C*')   => [228, 184, 173]

UTF-8和Unicode

不清除具体原因,在Ruby 1.9.3中,UTF-8字符串和Uniocde有一种特殊的自动转化方式(低于Ruby 1.9的版本,没有Unicode的支持),会自动进行转化,只要UTF-8字节串给加上了UTF-8的编码信息,字符串就自动转化为Unicode模式了。

"\xE4\xB8\xAD".force_encoding('UTF-8') == "\u4E2D"      =>     true

将Unicode转化为UTF-8字符串:

"\u4E2D".each_byte {|b| print b.to_s(16)} => 'e4b8ad' #可见Unicode底层用UTF-8字节串存储

#字符串格式
"\u4E2D" # 底层就是UTF-8串

#双字节数字格式
0x4E2D(16进制) 或者 20013(10进制) => [0x4E2D].pack('U*') => "\u4E2D"

 

Categories: ruby on rails 标签:
  1. 还没有评论呢。