Kratka priča o FEFF-u, nevidljivom UTF-8 liku koji je uništio naše CSV datoteke

Danas smo naišli na pogrešku prilikom pokušaja stvaranja nekih sjemena baze podataka iz CSV-a. Ovaj CSV izvorno sam generirao pomoću Ruby skripte koja je izlazom poslala datoteku i spremila kao CSV.

CSV je prijavljen u Git i koristio se neko vrijeme dok nismo morali ažurirati neke njegove dijelove dodavanjem novog stupca i popravljanjem nekih vrijednosti.

Iako još ne znamo točan razlog, moja teorija glasi da je Excel za Mac (svi koristimo Mac) dodao neke dodatne metapodatke čak i nakon što je datoteku spremio kao CSV.

Zbog toga je netko tko koristi sjeme primio sljedeću pogrešku:

CSV::MalformedCSVError: Illegal quoting in line 1.

Otvorio sam CSV datoteku i ništa nije izgledalo sumnjivo. Moja prva misao bila je neki lijevi / desni navodnici su na neki način umiješani u datoteku umjesto da samo je „normalan” dvostruke navodnike: ". No, u daljnjoj istrazi nije bilo ništa neobično. To me dovelo do toga da samo izbrišem cijelu datoteku i zapravo opet upišem prvi red.

Ponovno sam spremio tu datoteku i pokrenuo migraciju:

CSV::MalformedCSVError: Illegal quoting in line 1.

Što?!

Ok, ovo me izluđivalo. Otvorio sam novu datoteku, ponovno upisao točno jedan redak i pokrenuo migraciju. Upalilo je. Pa što je bilo u tom dosjeu ?!

Samo jedan način da saznate:

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

Dakle, OSX ima ove dvije vrlo korisne funkcije: pbcopyi pbpaste. Uglavnom sve što se unese pbcopyu vaš međuspremnik i pbpastestavi ono što imate na međuspremnik na standardni izlaz (stdout). Ali uklanja sve formatiranje.

Vrlo korisno kada želite kopirati tekst odnekud i želite ga zalijepiti u WYSIWYG editor bez sveg oblikovanja. Kao kad na primjer pišete e-poštu s Gmaila.

Zatim sam uklonio izvornu datoteku i spremio novu 'neformatiranu' datoteku s istim nazivom datoteke kako bih mogao vidjeti razliku.

I napokon smo vidjeli nevidljivog čovjeka:

Brza pretraga na Googleu rekla nam je da se naš prijatelj U+FEFFzvao ZERO WIDTH NO-BREAK SPACE. Također, brzi odlazak na Wikipediju rekao nam je o stvarnoj upotrebi za U+FEFF, poznatiju kao Byte order markili BOM.

Naš prijatelj FEFFmisli na različite stvari, ali u osnovi je to signal programu kako čitati tekst. To može biti UTF-8(češće) UTF-16, ili čak UTF-32.

FEFFsam je za UTF-16- u UTF-8njemu je poznatiji kao 0xEF,0xBB, or 0xBF.

Iz moje razumijevanje, kada je CSV datoteka otvori u Excelu i spasio, Excel stvorio prostor za naše nevidljive slijepih putnika, U+FEFF. I ispred datoteke za pokretanje!

Excel je učinio čaroliju i vjerojatno je spremljen UTF-16umjesto UTF-8. UTF-8ne razumije BOMi samo ga tretira kao ne-lik, tako da je vizualno datoteka bila u redu. Ali Ruby CSVpomisao da nešto nije u redu jer se pretpostavlja datoteku je čitanje je UTF-8i ne može ignorirati Mr. U+FEFF.

Dakle, naučena lekcija: ne otvarajte (i spremajte!) CSV datoteku u Excelu ako je želite uvesti u CSVRubyev parser.

Ako ikad naiđete na takvu pogrešku, potražite skrivene znakove koje vaš urednik ne prikazuje. Ako ga i dalje ne možete vidjeti i upotrebljavate OSX, tada će vam pbcopyi pbpastepomoći - uklanjaju iz teksta svako oblikovanje ili skrivene znakove, uz kopiranje i lijepljenje.