nous permettons aux utilisateurs d'importer des données via csv (en utilisant Ruby 1.9.2, donc c'est plus rapidecsv).
étant des données utilisateur, bien sûr, elles pourraient ne pas être correctement nettoyées.
Lorsque nous essayons d'afficher les données dans une méthode/index, nous obtenons parfois l'erreur "séquence d'octets invalide en UTF-8" pointant vers notre erb où nous affichons l'un des champs widget.name
Lorsque nous faisons l'importation, nous aimerions forcer les données entrantes à être valides ... y a-t-il un opérateur Ruby qui mappera une chaîne à une chaîne utf8 valide, par exemple, quelque chose comme
goodstring = badstring.no_more_invalid_bytes
Un exemple de "mauvaises" données est le caractère qui ressemble à un trait d'union mais qui n'est pas un trait d'union ascii normal. Nous préférons mapper les caractères non-utf-8 à un équivalent ascii raisonnable (umlat-u devenant u pour exmaple) MAIS nous sommes d'accord pour simplement supprimer le caractère.
puisque c'est lors de l'importation de beaucoup de données, il doit être un opérateur intégré rapide, je l'espère ...
Remarque: voici un exemple des données. Le fichier vient de Windows et est en 8 bits ascii. lorsque nous l'importons et dans notre erb nous affichons widget.name.inspect (au lieu de widget.name) nous obtenons: "Chains\x96 Accessories"
donc un exemple des données est un "tiret" qui est en fait le code 8 bits 96.
--- lorsque nous avons modifié notre analyse csv pour attribuer fldval = d.encode ('UTF-8'), il renvoie cette erreur:
Encoding::UndefinedConversionError in StoresController#importfinderitems
"\x96" from ASCII-8BIT to UTF-8
ce que nous recherchons est un moyen simple de le forcer à être valide utf8 quel que soit le type d'origine, même si nous supprimons simplement les non-ascii.
bien qu'il ne soit pas aussi agréable que de forcer l'encodage, cela fonctionne à un léger coût pour notre temps d'importation: d.to_s.strip.gsub (/\P {ASCII} /, '') Merci, Mladen!
Ruby 1.9 CSV a un nouvel analyseur qui fonctionne avec m17n. L'analyseur fonctionne avec l'encodage de IO objet dans la chaîne. Méthodes suivantes: ::foreach, ::open, ::read, and ::readlines
pourrait prendre des options facultatives :encoding
dont vous pouvez spécifier l'encodage.
Par exemple:
CSV.read('/path/to/file', :encoding => 'windows-1251:utf-8')
Convertirait toutes les chaînes en UTF-8.
Vous pouvez également utiliser le nom d'encodage plus standard "ISO-8859-1"
CSV.read('/..', {:headers => true, :col_sep => ';', :encoding => 'ISO-8859-1'})
J'ai répondu à une question similaire qui traite de la lecture de fichiers externes dans 1.9.2 avec des encodages non UTF-8. Je pense que cette réponse vous aidera beaucoup: problème d'encodage de caractères dans Rails v3/Ruby 1.9.2
Notez que vous devez connaître le codage source pour que vous puissiez le convertir de manière fiable. Il y a des bibliothèques comme celle à laquelle j'ai lié dans mon autre réponse qui peuvent vous aider à déterminer cela.
De plus, si vous ne chargez pas les données d'un fichier, vous pouvez convertir l'encodage d'une chaîne en 1.9.2 assez facilement:
'string'.encode('UTF-8')
Cependant, il est rare que vous construisiez une chaîne dans un autre encodage, et il est préférable de la convertir au moment où elle est lue dans votre environnement si possible.
CSV.parse(File.read('/path/to/csv').scrub)
Ruby 1.9 peut changer l'encodage des chaînes avec une détection et un remplacement invalides:
str = str.encode('UTF-8', :invalid => :replace)
Pour les chaînes inhabituelles telles que les chaînes chargées à partir d'un fichier d'encodage inconnu, il est judicieux d'utiliser #encode au lieu d'une expression régulière, #gsub ou #delete, car elles ont toutes besoin d'analyser la chaîne - mais si la chaîne est cassée, il ne peut pas être analysé, donc ces méthodes échouent.
Si vous recevez un message comme celui-ci:
error ** from ASCII-8BIT to UTF-8
Ensuite, vous essayez probablement de convertir une chaîne binaire qui est déjà en UTF-8, et vous pouvez forcer UTF-8:
str.force_encoding('UTF-8')
Si vous savez que la chaîne d'origine n'est pas en UTF-8 binaire, ou si la chaîne de sortie a des caractères illicites, alors lisez la suite sur Ruby encoding translittérations.
Si vous utilisez Rails , vous pouvez essayer de le réparer avec les éléments suivants
'Your string with strange stuff #@~'.mb_chars.tidy_bytes
Il vous supprime les caractères utf-8 invalides et les remplace par des caractères valides. Plus d'informations: https://apidock.com/Rails/String/mb_chars
Importez le fichier CSV dans la feuille de calcul Google Docs et téléchargez-le à nouveau en tant que fichier CSV. Importez et le tour est joué! (A travaillé dans mon cas)
Vraisemblablement, Google le convertit au format souhaité.
Ne faites que ça
anyobject.to_csv(:encoding => 'utf-8')
Comme mentionné par quelqu'un d'autre, scrub fonctionne bien pour le nettoyer dans Ruby 2.1+. Si vous avez un gros fichier, vous ne voudrez peut-être pas lire le tout en mémoire, vous pouvez donc utiliser scrub comme ça:
data = IO::read(file_path).scrub("")
CSV.parse(data, :col_sep => ',', :headers => true) do |row|
puts row
end