2011-07-07 10 views
6

Estoy leyendo líneas de un archivo de texto usando (line-seq (reader "input.txt")). Esta colección es luego pasada y utilizada por mi programa.Usando `line-seq` con` reader`, ¿cuándo se cierra el archivo?

Me preocupa que este sea un mal estilo, ya que no estoy cerrando el archivo de manera determinista. Imagino que no puedo usar (with-open (line-seq (reader "input.txt"))), ya que la secuencia de archivos se cerrará antes de atravesar toda la secuencia.

¿Se debe evitar lazy-seq junto con reader para archivos? ¿Hay algún patrón diferente que debería usar aquí?

Respuesta

15

Dado que esta realidad no tiene una respuesta clara (todo se mezcla en los comentarios sobre la primera respuesta), aquí está la esencia de la misma:

(with-open [r (reader "input.txt")] 
    (doall (line-seq r))) 

que obligará a toda la secuencia de líneas para ser leído y cierra el archivo. A continuación, puede pasar el resultado de toda esa expresión.

Cuando se trata de archivos de gran tamaño, es posible que tenga problemas de memoria (que sostiene toda la secuencia de líneas en la memoria) y es entonces cuando se trata de una buena idea para invertir el programa:

(with-open [r (reader "input.txt")] 
    (doall (my-program (line-seq r)))) 

Usted puede o no puede necesitar doall en ese caso, dependiendo de lo que mi-programa regrese y/o si mi-programa consume la secuencia perezosamente o no.

0

Parece que el clojure.contrib.duck-streams/read-lines es justo lo que está buscando. read-lines cierra el archivo cuando no hay entrada y devuelve la secuencia como line-seq. Intente ver el código fuente de read-lines.

+1

clojure.contrib.duck-streams está en desuso: http://clojure.github.com/clojure-contrib/#duck-streams – pauldoo

+0

@pauldoo No me di cuenta de esto. Tienes razón, pero las funciones 'line-seq' y' read-line' usan el mismo patrón para recuperar cadenas del lector (por .readLine). Solo mírelos ([line-seq] (https://github.com/clojure/clojure/blob/f86db9cc68773dd3e4a166c1ff7b81e4a98aa602/src/clj/clojure/core.clj#L2314), [read-line] (https: // github.com/clojure/clojure-contrib/blob/aa3f018f65006c78b08703e7adef04b7f39e1542/src/main/clojure/clojure/contrib/duck_streams.clj#L236)), si quieres la pereza puedes tomar 'read-line' en tu código fuente. – m039

+0

@pauldoo Como puedo ver, otra solución es no utilizar la pereza y tomar todo el contenido en una variable o simplemente usar .close en el lector. Y debe usar 'with-open' como este' (con-open [r (reader "input.txt")] (make-smth-on-lines (line-seq r))) '. – m039

Cuestiones relacionadas