Я вытаскиваю некоторые каналы RSS с YouTube, которые имеют недопустимый UTF8. Я могу создать аналогичную строку 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?
возможно потому, что кодовая точка не лежит в базовом многоязычном плане который является единственным символом, который допускает MySQL в наборе символов "utf8".
В новых версиях mysql есть еще один набор символов, называемый "utf8mb4", который поддерживает символы Unicode вне BMP.
Но вы, вероятно, не хотите использовать это. Внимательно изучите ваши прецеденты. Немногие реальные человеческие языки (если они есть) используют символы вне BMP.
Я не полагаюсь на встроенный в 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-страницах).
Я создал свою собственную функцию проверки для "Модифицированного UTF-8", которая может принимать параметр: bmp_only для ограничения проверки на базовую многоязычную плоскость (0x1-0xffff). Этого должно быть достаточно для большинства современных языков (ссылка: https://en.wikipedia.org/wiki/Unicode_plane).
Найти валидатор здесь: https://gist.github.com/2295531