Ruby 2.0.0 String#Match ArgumentError: недопустимая последовательность байтов в UTF-8
Я вижу это много и не понял изящного решения. Если пользовательский ввод содержит недопустимые последовательности байтов, мне нужно, чтобы он не вызывал исключения. Например:
# @raw_response comes from user and contains invalid UTF-8
# for example: @raw_response = "xBF"
regex.match(@raw_response)
ArgumentError: invalid byte sequence in UTF-8
были заданы многочисленные подобные вопросы, и результат, по-видимому, кодирование или принудительное кодирование строки. Однако ни один из них не работает для меня:
regex.match(@raw_response.force_encoding("UTF-8"))
ArgumentError: invalid byte sequence in UTF-8
или
regex.match(@raw_response.encode("UTF-8", :invalid=>:replace, :replace=>"?"))
ArgumentError: invalid byte sequence in UTF-8
это ошибка с Ruby 2.0.0 или мне не хватает что-то?
что странно, кажется, кодировка правильно, но матч продолжает вызывать исключение:
@raw_response.encode("UTF-8", :invalid=>:replace, :replace=>"?").encoding
=> #<Encoding:UTF-8>
2 ответов
в Ruby 2.0 encode
метод является no-op при кодировании строки в ее текущую кодировку:
обратите внимание, что преобразование из кодировки
enc
в той же кодировкеenc
является no-op, т. е. приемник возвращается без каких-либо изменений, и никаких исключений не возникает, даже если есть недопустимые байты.
это изменилось в 2.1, который также добавил scrub
метод как более простой способ сделать этот.
если вы не можете обновить до 2.1, вам придется кодировать в другую кодировку и обратно, чтобы удалить недопустимые байты, что-то вроде:
if ! s.valid_encoding?
s = s.encode("UTF-16be", :invalid=>:replace, :replace=>"?").encode('UTF-8')
end
поскольку вы используете Rails, а не только Ruby, вы также можете использовать tidy_bytes. Это работает с Ruby 2.0, а также, вероятно, вернет вам разумные данные вместо просто замены символов.