En hurtig fortælling om FEFF, et usynligt UTF-8-tegn, der ødelagde vores CSV-filer

I dag stødte vi på en fejl under forsøget på at oprette nogle databasefrø fra en CSV. Denne CSV blev oprindeligt genereret af mig ved hjælp af et Ruby-script, som ledte output til en fil og blev gemt som en CSV.

CSV blev checket ind på Git og var blevet brugt et stykke tid, indtil vi var nødt til at opdatere nogle dele af det ved at tilføje en ny kolonne og rette nogle værdier.

Selvom vi endnu ikke ved den nøjagtige årsag, er min teori, at Excel til Mac på en eller anden måde (vi bruger alle Mac'er) tilføjede nogle ekstra metadata til det, selv efter at filen blev gemt som en CSV.

Dette fik igen alle, der bruger frøet, til at modtage følgende fejl:

CSV::MalformedCSVError: Illegal quoting in line 1.

Jeg åbnede CSV-filen, og intet så mistænkeligt ud. Min første tanke var nogle venstre / højre anførselstegn blev en eller anden måde blandet ind i fil i stedet for bare de 'normale' dobbelte anførselstegn: ". Men efter yderligere undersøgelse var der intet usædvanligt. Dette fik mig til bare at udslette hele filen og faktisk skrive den første række ud igen.

Jeg gemte den fil igen og kørte migreringen:

CSV::MalformedCSVError: Illegal quoting in line 1.

Hvad?!

Okay, det gjorde mig nødt. Jeg åbnede en ny fil, skrev den nøjagtige enkeltlinje igen og kørte migreringen. Det virkede. Så hvad var der i den fil ?!

Kun én måde at finde ud af:

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

Så OSX har disse to funktioner, der er meget nyttige: pbcopyog pbpaste. Dybest set alt, hvad der røres til, pbcopykommer ind i dit udklipsholder og pbpastesætter det, du har på dit udklipsholder, til standardoutput (stdout). Men det fjerner al formatering.

Meget nyttigt, når du bare vil kopiere tekst fra et sted, og du vil indsætte den i en WYSIWYG-editor uden al formatering. Som når du f.eks. Skriver en e-mail fra Gmail.

Jeg fjernede derefter den originale fil og gemte den nye 'uformaterede' fil med samme filnavn, så jeg kunne se forskellen.

Og endelig så vi den usynlige mand:

En hurtig Google-søgning fortalte os, at vores ven U+FEFFblev kaldt en ZERO WIDTH NO-BREAK SPACE. En hurtig tur til Wikipedia fortalte os også om de faktiske anvendelser til U+FEFF, mere almindeligt kendt som Byte order markeller BOM.

Vores ven FEFFbetyder forskellige ting, men det er dybest set et signal til et program om, hvordan man læser teksten. Det kan være UTF-8(mere almindeligt) UTF-16eller endda UTF-32.

FEFFi sig selv er for UTF-16- i UTF-8det er mere almindeligt kendt som 0xEF,0xBB, or 0xBF.

Fra min forståelse, når CSV-filen blev åbnet i Excel og gemt, skabte Excel en plads til vores usynlige blind passager, U+FEFF. Og foran filen for at starte!

Excel gjorde noget magisk, og det blev sandsynligvis gemt i UTF-16stedet for UTF-8. UTF-8forstår ikke BOMog behandler det bare som et ikke-tegn så visuelt, filen var okay. Men Rubys CSVtanke, at der var noget galt, fordi det antages fil det læste var UTF-8, og det kunne ikke ignorere mr U+FEFF.

Så erfaringen: Åbn ikke (og gem!) Ikke en CSV-fil i Excel, hvis du vil føje den til Rubys CSVparser.

Hvis du nogensinde støder på en sådan fejl, skal du kigge efter skjulte tegn, der ikke vises af din editor. Hvis du stadig ikke kan se det og bruger OSX, så pbcopyog pbpastevil hjælpe dig ud - de isolere eventuelle formatering eller skjulte tegn fra tekst i tillæg til at kopiere og indsætte den.