2012-12-09 3 views
5

Buon pomeriggio. Supponiamo di avere un file utf-8 con una singola lettera, diciamo "f" (no \ n e spazi) e cerco di ottenere una sequenza di lunghezze di linea.Lunghezza della prima riga in un file UTF-8 con BOM

(with-open [rdr (reader "test.txt")] 
    (doall (map #(.length %) (line-seq rdr)))) 

E ho

=> (2) 

Perché? C'è un modo elegante per ottenere la lunghezza giusta della prima stringa?

+0

Non riesco a riprodurlo. Ho usato il tuo codice con il file UTF-8 contenente caratteri a uno o due byte, entrambi con o senza '\ n' alla fine. In tutti i casi ho ottenuto '(1)'. Qual è la tua versione Clojure? – Jan

+2

Solo un pensiero casuale, cosa succede se si inserisce una distinta base nei file di test? – SirDarius

+0

La mia versione di Clojure è 1.4. Sì, in realtà è BOM. Come posso evitare il problema? –

risposta

7

Il problema di BOM in Java è coperto in Reading UTF-8 - BOM marker. Sembra che possa essere estratta distanza utilizzando BOMInputStream dal di Apache Commons o deve essere rimosso manualmente, vale a dire

(defn debomify 
    [^String line] 
    (let [bom "\uFEFF"] 
    (if (.startsWith line bom) 
     (.substring line 1) 
     line))) 

(doall (map #(.length %) (.split (debomify (slurp "test.txt")) "\n"))) 

Se si vuole leggere un file pigramente utilizzando line-seq, ad esempio perché è enorme, è necessario trattare la prima riga usando debomify. Quelli rimanenti possono essere letti normalmente. Quindi:

(defn debommed-line-seq 
    [^java.io.BufferedReader rdr] 
    (when-let [line (.readLine rdr)] 
    (cons (debomify line) (lazy-seq (line-seq rdr))))) 
+0

Grazie. Forse questa è una soluzione. –

+0

Grazie per la versione più dettagliata. –

+0

Forse il metodo più ottimale è quello di fare semplicemente (debomify (slurp "test.txt")) e quindi dividerlo. –

Problemi correlati