Ruby 2.1.5 - ArgumentError: invalid byte sequence in UTF-8

Ruby 2.1.5 - ArgumentError: invalid byte sequence in UTF-8

我在 Ruby 2.1.5 和 Rails 4 中遇到 UTF8 字符问题。

问题是,来自外部服务的数据是这样的:

"first_name"=>"ezgi \xE7enberci"
"last_name" => "\xFC\xFE\xE7\xF0i\xFE\xFE\xF6\xE7"

这些字符主要包括土耳其字母字符,例如“üğşiçö”。当应用程序尝试保存这些数据时,出现以下错误:

ArgumentError: invalid byte sequence in UTF-8
Mysql2::Error: Incorrect string value

我该如何解决这个问题?

这看起来不像是 utf-8 数据,所以这个异常是正常的。听起来你需要告诉 ruby 字符串实际上是什么编码:

some_string.force_encoding("windows-1254")

然后您可以使用 encode 方法转换为 UTF8。有一些 gems(例如 charlock_holmes)可以启发式地自动检测编码,如果你得到的是混合编码

怎么了

Ruby 认为您的字节序列无效,因为您的字符串不是 UTF-8。例如,使用 rchardet gem:

require 'chardet'
["ezgi \xE7enberci", "\xFC\xFE\xE7\xF0i\xFE\xFE\xF6\xE7"].map do str
  puts CharDet.detect str
end

#=> [{"encoding"=>"ISO-8859-2", "confidence"=>0.8600826867857209}, {"encoding"=>"windows-1255", "confidence"=>0.5807177322740268}]

如何修复

您需要先使用 String#scrub or one of the encoding methods like String#encode! 清理字符串。例如:

hash = {"first_name"=>"ezgi \xE7enberci",
        "last_name"=>"\xFC\xFE\xE7\xF0i\xFE\xFE\xF6\xE7"}
hash.each_pair { |k,v| k[v.encode! "UTF-8", "ISO-8859-2"] }
#=> {"first_name"=>"ezgi çenberci", "last_name"=>"üţçđiţţöç"}

显然,您可能需要进行一些实验才能弄清楚正确的编码是什么(例如 ISO-8859-2、windows-1255 或其他完全不同的编码),但要确保您拥有一致的编码数据集的编码对您来说至关重要。

字符编码检测不完善。最好的办法是尝试找出外部数据源使用的编码,并在字符串编码中使用它,而不是尝试自动检测它。否则,您的里程可能会有所不同。