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: pbcopy
og pbpaste
. Dybest set alt, hvad der røres til, pbcopy
kommer ind i dit udklipsholder og pbpaste
sæ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+FEFF
blev 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 mark
eller BOM
.
Vores ven FEFF
betyder 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-16
eller endda UTF-32
.
FEFF
i sig selv er for UTF-16
- i UTF-8
det 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-16
stedet for UTF-8
. UTF-8
forstår ikke BOM
og behandler det bare som et ikke-tegn så visuelt, filen var okay. Men Rubys CSV
tanke, 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 CSV
parser.
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å pbcopy
og pbpaste
vil hjælpe dig ud - de isolere eventuelle formatering eller skjulte tegn fra tekst i tillæg til at kopiere og indsætte den.