когда мы импортируем данные CSV, как устранить «недопустимую последовательность байтов в UTF-8» - PullRequest
59 голосов
/ 19 февраля 2011

мы разрешаем пользователям импортировать данные через CSV (используя ruby ​​1.9.2, следовательно, он быстрее CSV).

данные пользователя, конечно, могут быть неправильно очищены.

Когда мы пытаемся отобразить данные в методе / index, мы иногда получаем ошибку «Недопустимая последовательность байтов в UTF-8», указывающую на наш erb, где мы отображаем одно из полей widget.name

Когда мы делаем импорт, мы хотим, чтобы входящие данные были ПРАВИЛЬНЫМИ ... есть ли оператор ruby, который отобразит строку в допустимую строку utf8, например, что-то вроде

goodstring = badstring.no_more_invalid_bytes

Одним из примеров «плохих» данных является char, который выглядит как дефис, но не является обычным ascii дефисом. Мы предпочли бы сопоставить символы non-utf-8 с разумным эквивалентом ascii (umlat-u будет u для примера), НО мы в порядке с простым разделением символа на.

, поскольку это при импорте большого количества данных, он должен быть быстрым встроенным оператором, надеюсь ...


Примечание: вот пример данных. Файл приходит из окон и является 8-битным ASCII. когда мы импортируем его и в нашем эрбе мы отображаем widget.name.inspect (вместо widget.name), мы получаем: "Цепочки \ x96 Аксессуары"

поэтому одним из примеров данных является "дефис", который на самом деле является 8-битным кодом 96.

--- когда мы изменили наш синтаксический анализ csv для назначения fldval = d.encode ('UTF-8') выдает эту ошибку:

Encoding::UndefinedConversionError in StoresController#importfinderitems
"\x96" from ASCII-8BIT to UTF-8

то, что мы ищем, это простой способ заставить его быть действительным utf8 независимо от типа источника, даже если мы просто удаляем non-ascii.


хотя и не так «приятно», как форсирование кодирования, это работает с небольшим расходом на наше время импорта: d.to_s.strip.gsub (/ \ P {ASCII} /, '') Спасибо тебе, Младен!

Ответы [ 8 ]

121 голосов
/ 26 июля 2012

В Ruby 1.9 CSV появился новый парсер, который работает с m17n. Парсер работает с кодированием объекта ввода-вывода в строке. Следующие методы: ::foreach, ::open, ::read, and ::readlines может принимать необязательные опции :encoding, которые вы можете указать кодировку.

Например:

CSV.read('/path/to/file', :encoding => 'windows-1251:utf-8')

Преобразует все строки в UTF-8.

Также вы можете использовать более стандартное название кодировки 'ISO-8859-1'

CSV.read('/..', {:headers => true, :col_sep => ';', :encoding => 'ISO-8859-1'})
13 голосов
/ 19 февраля 2011

Я ответил на аналогичный вопрос, который касается чтения внешних файлов в 1.9.2 с кодировками не-UTF-8.Я думаю, что ответ вам очень поможет: Проблема с кодировкой символов в Rails v3 / Ruby 1.9.2

Обратите внимание, что вам нужно знать исходную кодировку, чтобы преобразовать ее надежно.Есть библиотеки, подобные той, на которую я ссылался в моем другом ответе, которая может помочь вам определить это.

Кроме того, если вы не загружаете данные из файла, вы можете преобразовать кодировку строки в 1.9.2 довольно легко:

'string'.encode('UTF-8')

Однако редко вы строите строку в другой кодировке, и лучше всего конвертировать ее, когда это возможно, в вашу среду.

10 голосов
/ 25 июня 2016
CSV.parse(File.read('/path/to/csv').scrub)
7 голосов
/ 21 июля 2012

Ruby 1.9 может изменить строковое кодирование с неправильным обнаружением и заменой:

str = str.encode('UTF-8', :invalid => :replace)

Для необычных строк, таких как строки, загруженные из файла с неизвестной кодировкой, целесообразно использовать #encode вместо regex, #gsub или #delete, потому что для всех этих строк требуется синтаксический анализ - но если строка сломан, он не может быть проанализирован, поэтому эти методы не работают.

Если вы получаете сообщение, подобное этому:

error ** from ASCII-8BIT to UTF-8

Тогда вы, вероятно, пытаетесь преобразовать двоичную строку, которая уже есть в UTF-8, и вы можете форсировать UTF-8:

str.force_encoding('UTF-8')

Если вы знаете, что исходная строка отсутствует в двоичном кодировке UTF-8 или если в выходной строке содержатся нелегальные символы, прочитайте транслитерации Ruby.

4 голосов
/ 09 августа 2017

Если вы используете Rails , вы можете попытаться исправить это с помощью следующих

'Your string with strange stuff #@~'.mb_chars.tidy_bytes

Он удаляет недопустимые символы utf-8 и заменяет их действительными.Дополнительная информация: https://apidock.com/rails/String/mb_chars

1 голос
/ 26 ноября 2012

Загрузите файл CSV в таблицу Google Docs и повторно загрузите его как файл CSV. Импорт и вуаля! (Работал в моем случае)

Предположительно, Google конвертирует его в нужный формат.

Источник: Excel в CSV с кодировкой UTF-8

0 голосов
/ 16 февраля 2018

Как уже упоминалось, scrub хорошо работает, чтобы убрать это в Ruby 2.1+.Если у вас большой файл, вы, возможно, не захотите прочитать все это в памяти, поэтому вы можете использовать scrub следующим образом:

data = IO::read(file_path).scrub("")
CSV.parse(data, :col_sep => ',', :headers => true)  do |row|
   puts row
end
0 голосов
/ 26 ноября 2013

Только сделай это

anyobject.to_csv(:encoding => 'utf-8')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...