Un petit récit sur FEFF, un personnage UTF-8 invisible qui a détruit nos fichiers CSV

Aujourd'hui, nous avons rencontré une erreur en essayant de créer des bases de données à partir d'un CSV. Ce CSV a été généré à l'origine par moi à l'aide d'un script Ruby qui a redirigé la sortie vers un fichier et enregistré au format CSV.

Le CSV a été archivé dans Git et a été utilisé pendant un certain temps jusqu'à ce que nous devions en mettre à jour certaines parties en ajoutant une nouvelle colonne et en corrigeant certaines valeurs.

Bien que nous ne sachions pas encore la raison exacte, ma théorie est qu'en quelque sorte, Excel pour Mac (nous utilisons tous des Mac) a ajouté des métadonnées supplémentaires même après avoir enregistré le fichier au format CSV.

Cela a amené toute personne utilisant la graine à recevoir l'erreur suivante:

CSV::MalformedCSVError: Illegal quoting in line 1.

J'ai ouvert le fichier CSV et rien ne semblait suspect. Ma première pensée était des guillemets gauche / droite ont été mélangés en quelque sorte dans le fichier au lieu de simplement les doubles « normales » entre guillemets: ". Mais après une enquête plus approfondie, il n'y avait rien d'extraordinaire. Cela m'a conduit à effacer tout le fichier et à taper à nouveau la première ligne.

J'ai de nouveau enregistré ce fichier et exécuté la migration:

CSV::MalformedCSVError: Illegal quoting in line 1.

Quoi?!

D'accord, ça me rendait fou. J'ai ouvert un nouveau fichier, tapé à nouveau la ligne unique exacte et exécuté la migration. Ça a marché. Alors, qu'y avait-il dans ce fichier?!

Qu'une seule façon de le savoir:

cat companies.csv | pbcopy | pbpaste > temp.csv rm companies.csv mv temp.csv companies.csv git diff

OSX a donc ces deux fonctions très utiles: pbcopyet pbpaste. Fondamentalement, tout ce qui est canalisé pbcopyentre dans votre presse-papiers et pbpastemet ce que vous avez dans votre presse-papiers en sortie standard (stdout). Mais cela supprime tout formatage.

Très utile lorsque vous souhaitez simplement copier du texte de quelque part et que vous souhaitez le coller dans un éditeur WYSIWYG sans tout le formatage. Comme lors de la rédaction d'un e-mail depuis Gmail, par exemple.

J'ai ensuite supprimé le fichier d'origine et enregistré le nouveau fichier «non formaté» avec le même nom de fichier afin que je puisse voir la différence.

Et nous avons enfin vu l'homme invisible:

Une recherche rapide sur Google nous a appris que notre ami U+FEFFs'appelait un ZERO WIDTH NO-BREAK SPACE. En outre, un rapide voyage sur Wikipedia nous a parlé des utilisations réelles de U+FEFF, plus communément appelé Byte order markou BOM.

Notre ami FEFFveut dire des choses différentes, mais c'est essentiellement un signal pour un programme sur la façon de lire le texte. Cela peut être UTF-8(plus courant) UTF-16, ou même UTF-32.

FEFFlui-même est pour UTF-16- dans UTF-8il est plus communément appelé 0xEF,0xBB, or 0xBF.

D'après ce que j'ai compris, lorsque le fichier CSV a été ouvert dans Excel et enregistré, Excel a créé un espace pour notre passager clandestin invisible U+FEFF. Et devant le fichier pour démarrer!

Excel a fait de la magie, et il a probablement été enregistré au UTF-16lieu de UTF-8. UTF-8ne comprend pas BOMet le traite simplement comme un non-caractère donc visuellement, le fichier était correct. Mais Ruby CSVpensait qu'il y avait quelque chose qui n'allait pas parce qu'elle supposait que le fichier qu'elle lisait était UTF-8et qu'elle ne pouvait pas ignorer M U+FEFF..

Alors leçon apprise: n'ouvrez pas (et n'enregistrez pas!) Un fichier CSV dans Excel si vous voulez le transmettre à l' CSVanalyseur Ruby .

Si jamais vous rencontrez une erreur comme celle-là, assurez-vous de rechercher des caractères cachés non affichés par votre éditeur. Si vous ne pouvez toujours pas le voir et que vous utilisez OSX, alors pbcopyet pbpastevous aidera - ils suppriment tout formatage ou caractères cachés du texte en plus de le copier et de le coller.