web-dev-qa-db-fra.com

Ruby 2.0.0 String # Match ArgumentError: séquence d'octets invalide en UTF-8

Je vois beaucoup cela et je n'ai pas trouvé de solution gracieuse. Si l'entrée utilisateur contient des séquences d'octets invalides, je dois pouvoir ne pas déclencher d'exception. Par exemple:

# @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

De nombreuses questions similaires ont été posées et le résultat semble coder ou forcer le codage de la chaîne. Aucun de ces travaux pour moi cependant:

regex.match(@raw_response.force_encoding("UTF-8"))
ArgumentError: invalid byte sequence in UTF-8

ou

regex.match(@raw_response.encode("UTF-8", :invalid=>:replace, :replace=>"?"))
ArgumentError: invalid byte sequence in UTF-8

Est-ce un bogue avec Ruby 2.0.0 ou est-ce que je manque quelque chose?

Ce qui est étrange, c'est qu'il semble encoder correctement, mais la correspondance continue de soulever une exception:

@raw_response.encode("UTF-8", :invalid=>:replace, :replace=>"?").encoding
 => #<Encoding:UTF-8>
26
Tom Rossi

Dans Ruby 2.0 la méthode encode est un no-op lors du codage d'une chaîne dans son codage actuel:

Veuillez noter que la conversion d'un codage enc vers le même codage enc est un no-op, c'est-à-dire que le récepteur est retourné sans aucune modification, et aucune exception n'est levée, même s'il y a des octets invalides .

Cela a changé en 2.1, qui a également ajouté la méthode scrub comme un moyen plus facile de le faire.

Si vous ne parvenez pas à effectuer la mise à niveau vers 2.1, vous devrez encoder dans un autre encodage et inverser afin de supprimer les octets invalides, quelque chose comme:

if ! s.valid_encoding?
  s = s.encode("UTF-16be", :invalid=>:replace, :replace=>"?").encode('UTF-8')
end
44
matt

Puisque vous utilisez Rails et pas seulement Ruby vous pouvez également utiliser tidy_bytes . Cela fonctionne avec Ruby 2.0 et vous donnera probablement des données sensibles au lieu de simplement remplacer des caractères.

6
Yogh