Неверная последовательность байтов в UTF-8 из файла Excel - PullRequest
0 голосов
/ 14 октября 2019

(Ruby 2.5) У меня есть метод, который читает и анализирует файл CSV, который загружается через Alchemy CMS

def process_csv(csv_file, current_user_id, original_filename)
    lock_importer

    errors           = []
    index            = 0
    string_converter = lambda { |field| field.strip }
    total            = CSV.foreach(csv_file, headers: true).count
    csv_string = csv_file.read.encode!("UTF-8", "iso-8859-1", invalid: :replace)

    CSV.parse(csv_string, headers: true, header_converters: :symbol, skip_blanks: true, converters: [string_converter] ) do |row|
    # do other stuff
end

, но когда я пытаюсь загрузить файл CSV, имеющий столбец (имя) сстрока, содержащая специальные символы, тогда я получаю ошибку Invalid Byte Sequence in UTF-8. Я пытаюсь проверить значение N'öt Réal Stô'rë.

Я пробовал несколько решений, которые я нашел в Интернете, но безуспешно - есть предложения?

1 Ответ

0 голосов
/ 18 октября 2019

Неясно, какой у вас csv_file. Я предполагаю, что это File-объект.

Иногда я получал CSV из Excel как UTF-16. Итак, давайте попробуем пример:

У меня есть CSV-файл, хранящийся в UTF-16BE со следующим содержанием:

line;comment;UmlautÄ
1;Das ist UTF-16 BE;Ä
2;öüäÖÄÜ;Ä

Если я выполню следующий код:

require 'csv'
def process_csv(csv_file)
    csv_string = csv_file.read#.encode!("UTF-8", "iso-8859-1", invalid: :replace)
    CSV.parse(csv_string, headers: true, skip_blanks: true, col_sep: ';') do |row|
      p row # do other stuff
    end
end

process_csv(File.open('example_utf16BE.txt'))

тогда я получаю также Invalid byte sequence in UTF-8 -ошибку.

Если я использую

process_csv(File.open('example_utf16BE.txt', 'rb', encoding: 'BOM|utf-16BE'))

, тогда все работает.

Итак, я думаю, вы получите файл-объект в кодировке wron и код csv_file.read.encode!("UTF-8", "iso-8859-1", invalid: :replace) является частью кода для устранения этой проблемы.

Что вы можете сделать:

Добавить к вам код:

    p csv_file
    p csv_file.external_encoding

Вы должны получить

#<File:example_utf16BE.txt>
#<Encoding:UTF-16BE>

Теперь проверьте, действительно ли файл (в моем примере: example_utf16BE.txt действительно имеет кодировку 2-й строки.

Если нет, попробуйте адаптироватьСоздание файла-объекта. Если это невозможно, то вы можете попытаться использовать csv_file.set_encoding 'utf-8' для изменения кодировки, прежде чем читать содержимое.

...