Ошибка кодирования 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) является правильным символом без ручной проверки работоспособности.