2016-04-12 14 views
9

Voglio leggere le prime n righe da un file usando clojure. Qui è il mio codice:Come leggere n righe da un file in clojure

(defn read-nth-line [file] 
    (with-open [rdr (reader file)] 
    (loop [line-number 0] 
     (when (< line-number 20) 
      (nth (line-seq rdr) line-number) 
      (recur (inc line-number)))))) 

ma quando corro

user=> (read-nth-line "test.txt") 

IndexOutOfBoundsException clojure.lang.RT.nthFrom (RT.java:871) 

non ho idea del perché ho ottenuto un errore del genere.

+0

'test.txt' contiene più di 20 righe? – ClasG

+0

Puoi aggiungere il requisito alla tua domanda? Mi piace essere in grado di copiare il codice di pasta nel REPL: (richiede '[clojure.java.io: refer [reader]]) –

risposta

18

Il codice genera un errore di limite perché si chiama line-seq più volte sullo stesso lettore. Se si desidera ottenere un certo numero di linee da un lettore, si dovrebbe chiamare line-seq solo una volta, poi prendere il numero desiderato di linee da quella sequenza:

(require '[clojure.java.io :as io]) 

(defn lines [n filename] 
    (with-open [rdr (io/reader filename)] 
    (doall (take n (line-seq rdr))))) 

Esempio:

(run! println (lines 20 "test.txt")) 

Se test.txt contiene meno di 20 righe, questo semplicemente stamperà tutte le linee nel file.

+0

Puoi aggiungere il requisito alla tua risposta? Mi piace poter copiare il codice incolla nel REPL (richiede '[clojure.java.io: refer [reader]]) –

+1

@MichielBorkent Sure; Stavo solo cercando di rispecchiare lo stile dell'OP. Ho aggiunto un 'require' con un alias, perché preferisco usare': as' su ': refer' quando è fattibile. –

Problemi correlati