为什么ruby在mysql没有检测到无效编码?

时间:2011-05-09 02:15:45

标签: mysql ruby utf-8 internationalization utf8mb4

我从YouTube中提取了一些包含无效UTF8的RSS源。我可以使用

创建一个类似的ruby字符串
bad_utf8 = "\u{61B36}"
bad_utf8.encoding # => #<Encoding:UTF-8>
bad_utf8.valid_encoding? # => true

Ruby认为这是一个有效的UTF-8编码,我很确定它不是。

与Mysql交谈时,我得到一个错误

require 'mysql2'
client = Mysql2::Client.new(:host => "localhost", :username => "root")
client.query("use test");

bad_utf8 = "\u{61B36}"
client.query("INSERT INTO utf8 VALUES ('#{moo}')")

# Incorrect string value: '\xF1\xA1\xAC\xB6' for column 'string' at row 1 (Mysql2::Error)

在将这些无效类型的编码发送到MySQL之前,如何检测或修复这些无效类型的编码?

2 个答案:

答案 0 :(得分:2)

我不依赖Ruby的内置String.valid_encoding ?,因为以下内容也是可能的:

irb
1.9.3-p125 :001 > bad_utf8 = "\u{0}"
 => "\u0000" 
1.9.3-p125 :002 > bad_utf8.valid_encoding?
 => true 
1.9.3-p125 :003 > bad_utf8.encoding
 => #<Encoding:UTF-8>

这是有效的UTF-8(参考:https://en.wikipedia.org/wiki/Utf8),但我发现字符串中存在NULL字符通常暗示先前的转换错误(例如,当从无效的编码信息中转码时html页面。)

我为“Modified UTF-8”创建了自己的验证函数,它可以使用:bmp_only选项将验证限制为基本多语言平面(0x1-0xffff)。对于大多数现代语言来说,这应该足够了(参考:https://en.wikipedia.org/wiki/Unicode_plane)。

在此处找到验证器:https://gist.github.com/2295531

答案 1 :(得分:1)

可能是因为代码点不在basic multilingual plane  这是MySQL在其“utf8”字符集中允许的唯一字符。

较新版本的mysql有另一个名为“utf8mb4”的字符集supports unicode characters outside the BMP

但你可能不想使用它。仔细考虑您的用例。很少有真正的人类语言(如果有的话)使用BMP之外的字符。