您的位置:首页 > 编程语言 > Ruby

Ruby:字符集和编码学习总结

2013-08-22 23:59 260 查看

背景

Ruby直到1.9版本才很好的支持了多字节编码,本文简单总结了今天学习的关于Ruby编码方面的知识。

字符串可以使用不同的编码

在.NET中字符串的编码是一致的,Ruby允许字符串有不同的编码,当时我就在想:如果两个不同编码的字符串相加会出现什么结果?

测试程序

# coding: utf-8

str_utf8 = "hi 段"
puts str_utf8.size                                # 4
puts str_utf8.bytesize                            # 6
puts str_utf8 .encoding                         # UTF-8
str_utf8.each_byte {|b| print "%02X," % }      # 68,69,20,E6,AE,B5,
puts

puts

str_gb2312 = "hi 段".encode("gb2312")
puts str_gb2312.size                            # 4
puts str_gb2312.bytesize                        # 5
puts str_gb2312 .encoding                         # GB2312
str_gb2312.each_byte {|b| print "%02X," % [b]}     # 68,69,20,B6,CE,
puts


[b]输出结果


4
6
UTF-8
68,69,20,E6,AE,B5,

4
5
GB2312
68,69,20,B6,CE,


备注:UTF-8对英文采用1个字节,对中文采用三个字节。GB2312对英文采用1个字节,对中文采用两个字节。

编码转换

编码转换可以采用String::encode("目标编码名称")来完成,如果编码之间的转换兼容,返回编码后的字符串,否则会抛出编码转换异常。

测试程序

begin
puts "段".encode("ascii")
rescue Exception => e
puts e.class
end

puts "段".encode("gb2312")


输出结果

Encoding::UndefinedConversionError
段


备注:encode会返回一个和元字符串序列一样的字符串序列,只是内部的字节序列改变了。

编码强制

编码强制是指在不改变字节序列的情况下改变对字节的解释方式,编码强制:String::force_encoding("强制编码")。

测试程序

utf8_str = "\xE6\xAE\xB5".encode("utf-8")
puts utf8_str.encoding() # UTF-8
puts utf8_str.size # 1
puts utf8_str.bytesize # 3

ascii_str = "\xE6\xAE\xB5".force_encoding("ascii")
puts ascii_str.encoding() # US-ASCII
puts ascii_str.size # 3
puts ascii_str.bytesize # 3
puts ascii_str.valid_encoding? # false


输出结果

UTF-8
1
3
US-ASCII
3
3
false


备注:String::valid_encoding?可以判定是否是有效的强制。

不同编码的字符串相加后是啥结果?

这个问题的答案很简单:如果两个字符串的编码兼容,则返回字符集最大的编码,否则跑出不兼容异常。你可以自己检查兼容性:Encoding.compatible?。

测试程序

str_ascii = "hi ".encode("ascii")
str_utf8 = "段"
puts str_ascii.encoding
puts str_utf8.encoding
puts Encoding.compatible?(str_ascii.encoding, str_utf8.encoding)
puts (str_ascii + str_utf8).encoding
puts (str_utf8 + str_ascii).encoding


运行结果

US-ASCII
UTF-8
UTF-8
UTF-8
UTF-8


一直没使用过的\u和\x

几乎所有的语言都支持这两个转义字符,允许我们使用\uXXXX指定Unicode码点对于的字符,通用也运行我们使用\xXX指定字节。

测试程序

puts "段" # 段
puts "\xE6\xAE\xB5" # 段
puts "\u6BB5" # 段


输出结果

# 段
# 段
# 段


使用Sublime开发Ruby时,输出到控制台的字符串为啥不能使用多种编码?

测试程序

puts "段"
puts "段".encode("GB2312")


在Sublime中的输出结果

[Decode error - output not utf-8]


在控制台的输出结果



原因分析

Sublime之所以失败是因为Sublime重定位了默认标准输出流,而重定位后的流不支持混合多种编码,说白了:你没法在一个文件中保存两种编码的字符串。

备注:Sublime中的失败不是Ruby导致的,是Sublime自身的问题。

如何解决?

Sublime默认只能接收UTF8编码,因此必须转换为UTF8编码。

# 默认是UTF8编码,不用处理。
puts "段"
# 执行windows命令必须使用GB2312编码。
command = "echo 段".encode("GB2312")
# 命令执行的结果想输出到Sublime必须使用UTF8编码。
puts `#{command}`.encode("utf-8")


输出结果

# 输出结果
段
段


备注

字符串、字符集和编码算是刚入门,有机会还得继续学习。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: