Come evitare di inciampare nella BOM UTF-8 durante la lettura dei file
-
23-08-2019 - |
Domanda
Sto consumando un feed di dati a cui è stata recentemente aggiunta un'intestazione BOM Unicode (U+FEFF) e il mio compito di rake ora ne è incasinato.
Posso saltare i primi 3 byte con file.gets[3..-1]
ma esiste un modo più elegante per leggere i file in Ruby in grado di gestirlo correttamente, indipendentemente dal fatto che sia presente o meno una distinta base?
Soluzione
Con Ruby 1.9.2 puoi utilizzare la modalità r:bom|utf-8
text_without_bom = nil #define the variable outside the block to keep the data
File.open('file.txt', "r:bom|utf-8"){|file|
text_without_bom = file.read
}
O
text_without_bom = File.read('file.txt', encoding: 'bom|utf-8')
O
text_without_bom = File.read('file.txt', mode: 'r:bom|utf-8')
Non importa se la distinta base è disponibile nel file o meno.
Puoi anche utilizzare l'opzione di codifica con altri comandi:
text_without_bom = File.readlines(@filename, "r:utf-8")
(Ottieni un array con tutte le linee).
Oppure con CSV:
require 'csv'
CSV.open(@filename, 'r:bom|utf-8'){|csv|
csv.each{ |row| p row }
}
Altri suggerimenti
Non saltato ciecamente i primi tre bytes; cosa succede se il produttore si ferma l'aggiunta di nuovo distinta base? Che cosa si dovrebbe fare è esaminare i primi byte, e se sono 0xEF 0xBB 0xBF, ignorarli. Questa è la forma il carattere BOM (U + FEFF) prende in UTF-8; Io preferisco trattare con esso prima di tentare di decodificare il flusso, perché la gestione della distinta base è così incoerente da una lingua / strumento / quadro a quella successiva.
In effetti, è così che sei dovrebbe per affrontare una distinta base. Se un file è stato servito come UTF-16, è necessario esaminare i primi due byte prima di iniziare la decodifica in modo da sapere se leggere come big-endian o little-endian. Naturalmente, l'UTF-8 BOM non ha nulla a che fare con l'ordine dei byte, è solo lì per farvi sapere che la codifica è UTF-8, nel caso non lo sa già che.
Mi piacerebbe non un file di "fiducia" per essere codificato come UTF-8 quando è presente una distinta di 0xEF 0xBB 0xBF, si potrebbe non riuscire. Di solito, quando il rilevamento del UTF-8 BOM, in realtà dovrebbe essere un file codificato UTF-8, naturalmente. Ma, se per esempio qualcuno ha appena aggiunto il BOM UTF-8 per un file ISO, che ci si riesce a codificare tale file così male se non ci sono byte in esso che sono al di sopra 0x0F. Ci si può fidare del file se si ha solo byte fino a 0x0F dentro, perché in questo caso si tratta di un file UTF-8 compatibile ASCII e allo stesso tempo si tratta di un file UTF-8 valido.
Se non ci sono solo i byte <= 0x0F all'interno del file (dopo il BOM), per essere sicuri che sia correttamente codifica UTF-8 si dovrà verificare la presenza di sequenze valide e - anche quando tutte le sequenze sono validi - assegno anche se ogni punto di codice da una sequenza utilizza la sequenza più breve possibile e controllare anche se non v'è alcun punto di codice che corrisponde a un alta o bassa surrogato. controllare anche se i byte massimo di una sequenza non è superiore a 4 e il codepoint massima è 0x10FFFF. I limiti massimi codepoint anche bit di payload del byte di start per essere non superiore a 0x4 e payload del primo byte successivo non superiore 0xF. Se tutti i controlli menzionati passano con successo, il tuo UTF-8 BOM dice la verità.