编码:: UndefinedConversionError

时间:2012-10-21 23:34:52

标签: ruby encoding sinatra sequel

每次尝试将哈希转换为JSON字符串时,我都会收到Encoding::UndefinedConversionError - "\xC2" from ASCII-8BIT to UTF-8。我尝试使用[.encode | .force_encoding](["UTF-8" | "ASCII-8BIT" ]),将.encode.force_encoding联系起来,向后切换参数但似乎没有任何效果,所以我抓住了这样的错误:

begin
  menu.to_json
rescue Encoding::UndefinedConversionError
  puts $!.error_char.dump
  p $!.error_char.encoding
end

其中menu是续集的dataset.to_hash,内容来自MySQL DB,utf8_general_ci编码并返回:

  

“\ XC2”

     

< #Encoding:ASCII-8BIT>

无论我使用的.encode / .force_encoding是什么,编码都不会改变。我甚至试图在没有运气的情况下替换字符串.gsub!(/\\\xC2/)

有什么想法吗?

5 个答案:

答案 0 :(得分:73)

menu.to_s.encode('UTF-8', invalid: :replace, undef: :replace, replace: '?')

这完美无缺,我不得不更换一些额外的字符,但没有更多错误。

答案 1 :(得分:16)

您对“\ xC2”的期望是什么?可能是Â

使用ASCII-8BIT你有二进制数据,并且ruby不能决定应该是什么。

您必须先使用force_encoding设置编码。

您可以尝试以下代码:

Encoding.list.each{|enc|
  begin
    print "%-10s\t" % [enc]
    print "\t\xC2".force_encoding(enc)
    print "\t\xC2".force_encoding(enc).encode('utf-8')
  rescue => err
    print "\t#{err}"
  end
  print "\n"
}

结果是“\ xC2”的不同编码中的可能值。

结果可能取决于你的输出格式,但我认为你可以做出一个很好的猜测,你有哪种编码。

当您定义所需的编码(可能是cp1251)时,您可以

menu.force_encoding('cp1252').to_json

另见Kashyaps评论。

答案 2 :(得分:10)

如果你不关心丢失奇怪的角色,你可以把它们吹走:

str.force_encoding("ASCII-8BIT").encode('UTF-8', undef: :replace, replace: '')

答案 3 :(得分:8)

您自动接受的解决方案不起作用,实际上没有错误,但它是 NOT JSON。

我使用oj gem解决了这个问题,它现在可以找到了。它也比标准的JSON库快。

写作:

   menu_json = Oj.dump menu

阅读:

   menu2 = Oj.load menu_json

https://github.com/ohler55/oj了解更多详情。我希望它会有所帮助。

答案 4 :(得分:1)

如果知道要替换的字符,

:fallback选项可能会有用

"Text ?".encode("ASCII", "UTF-8", fallback: {"?" => ":)"})
#=> hello :)

来自文档:

设置给定对象的替换字符串以定义未定义字符。该对象应该是Hash,Proc,Method或具有[]方法的对象。它的密钥是在当前代码转换器的源编码中编码的未定义字符。它的值可以是任何编码,直到可以将其转换为代码转换器的目标编码为止。