Mat*_*att 10 ruby string unicode encoding utf-8
要将字符串转换为UTF-8并替换所有编码错误,您可以执行以下操作:
str.encode('utf-8', :invalid=>:replace)
Run Code Online (Sandbox Code Playgroud)
唯一的问题是,如果str
已经是UTF-8,它就不起作用,在这种情况下,任何错误仍然存在:
irb> x = "foo\x92bar".encode('utf-8', :invalid=>:replace)
=> "foo\x92bar"
irb> x.valid_encoding?
=> false
Run Code Online (Sandbox Code Playgroud)
引用Ruby Docs:
请注意,从编码
enc
到相同编码的转换enc
是无操作,即接收器在没有任何更改的情况下返回,并且即使存在无效字节也不会引发异常.
显而易见的解决方法是首先转换为不同的Unicode编码,然后再转换回UTF-8:
str.encode('utf-16', :invalid=>:replace).encode('utf-8')
Run Code Online (Sandbox Code Playgroud)
例如:
irb> x = "foo\x92bar".encode('utf-16', :invalid=>:replace).encode('utf-8')
=> "foo?bar"
irb> x.valid_encoding?
=> true
Run Code Online (Sandbox Code Playgroud)
有没有更好的方法来做到这一点而不转换为虚拟编码?
mat*_*att 14
Ruby 2.1添加了一个String#scrub
执行您想要的方法:
2.1.0dev :001 > x = "foo\x92bar"
=> "foo\x92bar"
2.1.0dev :002 > x.valid_encoding?
=> false
2.1.0dev :003 > y = x.scrub
=> "foo?bar"
2.1.0dev :004 > y.valid_encoding?
=> true
Run Code Online (Sandbox Code Playgroud)
相同的提交也会改变行为,encode
以便在源和目标编码相同时它起作用:
2.1.0dev :005 > x = "foo\x92bar".encode('utf-8', :invalid=>:replace)
=> "foo?bar"
2.1.0dev :006 > x.valid_encoding?
=> true
Run Code Online (Sandbox Code Playgroud)
据我所知,在2.1之前没有内置的方法来执行此操作(否则scrub
将不需要),因此您需要使用一些解决方法技术,直到2.1发布并且您可以升级.
尝试这个:
"foo\x92bar".chars.select(&:valid_encoding?).join
# => "foobar"
Run Code Online (Sandbox Code Playgroud)
或者更换
"foo\x92bar".chars.map{|c| c.valid_encoding? ? c : "?"}.join
# => "foo?bar"
Run Code Online (Sandbox Code Playgroud)