Почему при чтении текстового файла возникает ошибка «Недопустимая последовательность байтов в UTF-8»? - PullRequest
1 голос
/ 16 июня 2011

Я пишу скрипт на Ruby для обработки большого текстового файла и получаю странную ошибку кодирования.Вот ситуация:

input_data = File.new(in_path, 'r').read
p input_data.encoding.name   #   UTF-8 
break_char = "\r".encode("UTF-8")
p break_char # "\r"
p break_char.encoding.name # "UTF-8" 
input_data.split(",".encode("UTF-8"))
p Encoding.compatible?(input_data, break_char) # # Encoding:UTF-8>

Это приводит к ошибке :in 'split': invalid byte sequence in UTF-8 (ArgumentError)

Я прочитал http://blog.grayproductions.net/articles/ruby_19s_string и посмотрел на другие решения, по-видимому, той же проблемы, но все еще не могувыяснить, почему это происходит, когда я считаю, что управляю кодировками.

Я работаю на OSX и работаю с ruby ​​1.9.2

Ответы [ 5 ]

8 голосов
/ 16 июня 2011

Очевидно, что ваш входной файл не UTF-8 (или, по крайней мере, не полностью).Если вас не волнуют символы, отличные от ascii, вы можете просто предположить, что ваш файл имеет кодировку ascii-8bit.Кстати, ваш разделитель (break_char) не вызывает проблем, так как запятая кодируется в UTF-8 так же, как и в ASCII.

fname = 'test.in'

# create example file and fill it with invalid UTF-8 sequence
File.open(fname, 'w') do |f|
  f.write "\xc3\x28"
end

# then try to read and parse it
s = File.open(fname) do |f| # file opened as UTF-8
#s = File.open(fname, 'r:ascii-8bit') do |f| # file opened as ascii-8bit
  f.read
end
p s.split ','
1 голос
/ 16 июня 2011

Вы читаете файл, используя кодировку по умолчанию, предоставляемую вашей системой. Таким образом, ruby ​​помечает строку как utf8, что не означает, что это действительно utf8-данные. Попробуйте file <input file> угадать, какая там кодировка, затем скажите ruby, что это именно она (unclean: force_encoding(<encoding>), clean: сообщите объекту File, что это за кодировка, я не знаю, как это сделать) а затем используйте encode!("utf8"), чтобы преобразовать его в utf8.

1 голос
/ 16 июня 2011

Я не могу получить ошибку здесь в Linux, даже если входной файл не UTF-8. (Я также использую Ruby 1.9.2.)

Логически, либо эта проблема связана с OS-X, либо связана с вашими входными данными. Это происходит независимо от данных во входном файле?

(Я понимаю, что это неправильный ответ, но мне не хватает представителя, чтобы добавить комментарий. И поскольку никто еще не ответил, я подумал, что это лучше, чем ничего ...)

0 голосов
/ 18 февраля 2016

Вот 2 распространенных ситуации и как с ними справиться:

Ситуация 1

У вас есть входной файл UTF-8 с возможно несколькими недопустимыми байтами
Удалить недействительные байты:

test = "Partly valid\xE4 UTF-8 encoding: äöüß"
File.open( 'input_file', 'w' ) {|f| f.write(test)}

str  = File.read( 'input_file' )

str.scrub('')
   => "Partly valid UTF-8 encoding: äöüß"

Ситуация 2

У вас есть входной файл, который может быть в кодировке UTF-8 или ISO-8859-1
Проверьте, какая это кодировка и конвертируйте в UTF-8 (при необходимости):

test = "String in ISO-8859-1 encoding: \xE4\xF6\xFC\xDF"
File.open( 'input_file', 'w' ) {|f| f.write(test)}

str  = File.read( 'input_file' )

unless str.valid_encoding?
  str.encode!( 'UTF-8', 'ISO-8859-1', invalid: :replace )
end #unless
   => "String in ISO-8859-1 encoding: äöüß"

Примечания

  • Приведенные выше фрагменты кода предполагают, что Ruby кодирует все ваши строки в UTF-8 по умолчанию. Несмотря на то, что это почти всегда так, вы можете убедиться в этом, запустив свои сценарии с # encoding: UTF-8.

  • Если указано неверно, программно возможно обнаружить большинство многобайтовых кодировок, таких как UTF-8 (в Ruby см .: #valid_encoding?). Однако НЕЛЬЗЯ (или, по крайней мере, крайне сложно) программно обнаружить недействительность однобайтовых кодировок, таких как ISO-8859-1. Таким образом, приведенный выше фрагмент кода не работает наоборот, то есть обнаруживает, является ли строка действительной кодировкой ISO-8859-1.

  • Хотя UTF-8 становится все более популярным в качестве кодировки по умолчанию в компьютерных системах, ISO-8859-1 и другие Latin1 разновидности все еще очень популярны в западных странах, особенно в Северной Америке. Имейте в виду, что существует несколько однобайтовых кодировок, которые очень похожи, но немного отличаются от ISO-8859-1. Примеры: CP1252 (a.k.a. Windows-1252), ISO-8859-15

[ruby] [кодировка] [utf8] [кодировка файла] [кодировка символов]

0 голосов
/ 09 апреля 2014

Пожалуйста, попробуйте это: -

input_data = File.open ("path / your_file.pdf", "rb") {| io | io.read}

Спасибо

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...