Подтвердить что ты не робот

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>
4b9b3361

Ответ 1

В 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

Ответ 2

Поскольку вы используете Rails, а не только Ruby, вы также можете использовать tidy_bytes. Это работает с Ruby 2.0, а также, вероятно, даст вам обратно разумные данные вместо обычных символов.