SmarterCSV и проблемы с кодировкой файлов в Ruby
Я работаю с файлом, который, кажется, имеет кодировку UTF-16LE. Если я бегу
File.read(file, :encoding => 'utf-16le')
первая строка файла:
"<U+FEFF>=\"25/09/2013\"\t18:39:17\t=\"Unknown\"\t=\"+15168608203\"\t\"Message.\"\r\n
Если я читаю файл, используя что-то вроде
csv_text = File.read(file, :encoding => 'utf-16le')
Я получаю сообщение об ошибке
ASCII incompatible encoding needs binmode (ArgumentError)
Если я переключу кодировку в приведенном выше
csv_text = File.read(file, :encoding => 'utf-8')
Я делаю это к SmarterCSV
часть кода, но появляется сообщение об ошибке
`=~': invalid byte sequence in UTF-8 (ArgumentError)
Полный код ниже. Если я запускаю это в консоли Rails, он работает просто отлично, но если я запускаю его, используя ruby test.rb
, это дает мне первую ошибку:
require 'smarter_csv'
headers = ["date_of_message", "timestamp_of_message", "sender", "phone_number", "message"]
path = '/path/'
Dir.glob("#{path}*.CSV").each do |file|
csv_text = File.read(file, :encoding => 'utf-16le')
File.open('/tmp/tmp_file', 'w') { |tmp_file| tmp_file.write(csv_text) }
puts 'made it here'
SmarterCSV.process('/tmp/tmp_file', {
:col_sep => "\t",
:force_simple_split => true,
:headers_in_file => false,
:user_provided_headers => headers
}).each do |row|
converted_row = {}
converted_row[:date_of_message] = row[:date_of_message][2..-2].to_date
converted_row[:timestamp] = row[:timestamp]
converted_row[:sender] = row[:sender][2..-2]
converted_row[:phone_number] = row[:phone_number][2..-2]
converted_row[:message] = row[:message][1..-2]
converted_row[:room] = file.gsub(path, '')
end
end
Обновление - 13.05.15
В конечном итоге я решил закодировать строку файла как UTF-8, а не углубляться в код SmarterCSV. Первая проблема в коде SmarterCSV состоит в том, что он не позволяет пользователю указывать двоичный режим при чтении в файле, но после настройки источника для обработки этого возникает множество других проблем, связанных с кодированием, многие из которых связаны с к обработке различных параметров в файлах, которые не были в кодировке UTF-8. Возможно, это был простой выход, но моя проблема была решена с помощью кодирования всего в UTF-8 до подачи его в SmarterCSV.
2 ответа
Добавьте binmode к File.read
вызов.
File.read(file, :encoding => 'utf-16le', mode: "rb")
Режим двоичного файла "b" Подавляет преобразование EOL <-> CRLF в Windows. И устанавливает внешнее кодирование в ASCII-8BIT, если явно не указано.
ссылка: http://ruby-doc.org/core-2.0.0/IO.html
Теперь передайте правильную кодировку в SmarterCSV
SmarterCSV.process('/tmp/tmp_file', {
:file_encoding => "utf-16le", ...
Обновить
Было установлено, что smartercsv
не поддерживает бинарный режим. После того, как ОП попытался изменить код безуспешно, было решено, что простым решением было преобразовать входные данные в UTF-8
который smartercsv
поддерживает.
К сожалению, вы используете стиль хранения "плоский файл", и кодирование символов будет проблемой с обеих сторон (чтение или запись).
Я бы предложил использовать что-то вроде str = str.force_encoding("UTF-8")
и посмотрим, сможете ли вы заставить это работать.