UTF-8 Ruby中的无效字节序列

时间:2015-07-07 15:20:35

标签: ruby character-encoding ruby-2.0

我有这样的字符串"abce\xC3".sub("a","A"),当我执行该行时,我得到以下错误。

ArgumentError: invalid byte sequence in UTF-8
    from (irb):20:in `sub'
    from (irb):20
    from /home/vijay/.rvm/rubies/ruby-2.0.0-p598/bin/irb:12:in `<main>'

有人可以帮我解决这个问题。

3 个答案:

答案 0 :(得分:7)

由于Arie已经回答了此错误,因为无效的字节序列\xC3

如果您使用的是Ruby 2.1 +,您还可以使用String#scrub替换给定替换字符的无效字节。这里:

a = "abce\xC3"
# => "abce\xC3" 
a.scrub
# => "abce�"
a.scrub.sub("a","A")
# => "Abce�"

答案 1 :(得分:5)

您需要弄清楚\xC3想要什么。它是否代表字符Ã

您会看到错误,因为\xC3在(默认)UTF-8编码中不是有效的字节序列。您可以先纠正字符串的编码(通过回答上面的问题),然后进行替换。

"abce\xC3".force_encoding("iso-8859-1").sub('a', 'A')

或者,如果编码无关紧要,例如,您正在处理字节序列而不是字符序列,则可以强制编码为ASCII-8BIT

"abce\xC3".force_encoding("ASCII-8BIT").sub('a', 'A')

答案 2 :(得分:2)

关于您的comment /实际问题:

  

"ITZVÃ"是文件的内容。当我读到文件时。

 z = File.open("x")
 z.read(5)
     

然后输出应为ITZV\xC3\x83而不是ITZV\xC3

这是因为在UTF-8中,Ã是一个多字节字符,即您的字符串有5个字符,但是6个字节

"ITZVÃ".chars #=> ["I", "T", "Z", "V", "Ã"]
"ITZVÃ".bytes #=> [ 73,  84,  90,  86, 195, 131]

z.read(5)从您的文件中读取5个字节,从而返回不完整的UTF-8字符串:

require 'tempfile'

z = Tempfile.new('foo')
z << 'ITZVÃ'

z.rewind
z.read(5) #=> "ITZV\xC3"

您必须阅读6个字节:

z.rewind
z.read(6) #=> "ITZV\xC3\x83"

请注意,read始终返回ASCII-8BIT编码的字符串。您必须手动设置不同的编码:

z.rewind
z.read(6).force_encoding('utf-8') #=> "ITZVÃ"