Ошибка кодирования postgres в приложении sidekiq

Я работаю над приложением, в котором процесс ruby ​​sidekiq вызывает третью сторону и анализирует данные в базе данных.

Я использую сиквел и мою форму.

Я получаю некоторые странные символы обратно в результатах, например:

"Tweets en Ingl \ xE9s y en Espa \ xF1ol"

При попытке сохранить в postgres возникает следующая ошибка:

Sequel:: DatabaseError: PG:: CharacterNotInRepertoire: ERROR: неверная последовательность байтов для кодировки "UTF8": 0xe9 0x73 0x20

Странно то, что строка думает, что это UTF-8, если я проверяю имя кодировки, она говорит:

name.encoding.name #UTF-8

Что я могу сделать, чтобы убедиться, что данные в правильном формате для postgres?

1 ответ

Решение

Тот факт, что строка называется UTF-8, не означает, что это UTF-8. \xe9 является é в ISO-8859-1 (AKA Latin-1), но он недействителен в UTF-8; так же, \xf1 является ñ в ISO-8859-1, но недействительным в UTF-8. Это говорит о том, что строка на самом деле кодируется в ISO-8859-1, а не в UTF-8. Вы можете исправить это с помощью комбинации force_encoding чтобы исправить путаницу Руби по поводу текущей кодировки и encode перекодировать его как UTF-8:

> "Tweets en Ingl\xE9s y en Espa\xF1ol".force_encoding('iso-8859-1').encode('utf-8')
=> "Tweets en Inglés y en Español" 

Поэтому перед отправкой этой строки в базу данных вы хотите:

name = name.force_encoding('iso-8859-1').encode('utf-8')

К сожалению, нет способа надежно определить реальное кодирование строки. Различные кодировки перекрываются, и нет никакой возможности определить, è (\xe8 в ISO-8859-1) или č (\xe8 в ISO-8859-2) является правильным символом без ручной проверки работоспособности.

Другие вопросы по тегам