Почему ruby не обнаруживает неверную кодировку, в то время как mysql это делает?

3

Я вытаскиваю некоторые каналы 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?

  • 0
    Поэтому я думаю, что проблема может заключаться в том, что MySQL поддерживает только базовую многоязычную плоскость, где ruby поддерживает все.
  • 0
    Руби поддерживает все? С каких пор?
Теги:
utf-8
internationalization
utf8mb4

2 ответа

1
Лучший ответ

возможно потому, что кодовая точка не лежит в базовом многоязычном плане  который является единственным символом, который допускает MySQL в наборе символов "utf8".

В новых версиях mysql есть еще один набор символов, называемый "utf8mb4", который поддерживает символы Unicode вне BMP.

Но вы, вероятно, не хотите использовать это. Внимательно изучите ваши прецеденты. Немногие реальные человеческие языки (если они есть) используют символы вне BMP.

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-страницах).

Я создал свою собственную функцию проверки для "Модифицированного UTF-8", которая может принимать параметр: bmp_only для ограничения проверки на базовую многоязычную плоскость (0x1-0xffff). Этого должно быть достаточно для большинства современных языков (ссылка: https://en.wikipedia.org/wiki/Unicode_plane).

Найти валидатор здесь: https://gist.github.com/2295531

  • 0
    \ u0000 действителен. Это исключение находится в контексте «модифицированного UTF-8», используемого Java DataInput / DataOutput docs.oracle.com/javase/6/docs/api/java/io/DataInput.html.
  • 0
    Правильно. Приведенная выше сущность использует Модифицированный UTF-8, и я сделаю это, чтобы прояснить ситуацию.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню