2010-09-28 16 views
6

Quiero leer el contenido de un archivo en una lista. Algunos de mis intentos han sido hasta ahora -¿Cómo puedo leer el contenido de un archivo en una lista en Lisp?

(defun get-file (filename) 
    (let ((x (open filename))) 
    (when x 
     (loop for line = (read-line x nil) 
    while line do (list line))) 
    (close x))) 

(defun get-file (filename) 
    (let ((x (open filename :if-does-not-exist nil)) (contents (list nil))) 
    (when x 
     (loop for line = (read-line x nil) 
    while line do (cons contents line))) 
    (close x) contents)) 

(defun get-file (filename) 
    (let ((x (open filename :if-does-not-exist nil)) (contents nil)) 
    (when x 
     (loop for line = (read-line x nil) 
    while line do (append contents line))) 
    (close x) contents)) 

Ninguno de ellos funcionó. ¿Alguien puede decirme una manera? O mejor aún: ¿cómo poner todos los contenidos en una matriz?

Respuesta

14

¿Qué tal

(defun get-file (filename) 
    (with-open-file (stream filename) 
    (loop for line = (read-line stream nil) 
      while line 
      collect line))) 
+0

(con-open-file (f nombre de archivo) ¿Por qué tiene un nombre de archivo antes de f allí? ¿Qué hace la línea colectora? ¿Y cómo colabora con while line al final? – Sterling

+3

'with-open-file' abre el archivo llamado' filename' y asocia la secuencia con 'f'. 'collecting' recoge los diversos valores de' line' en una lista, hasta que 'while' es' nil'. ¡Common Lisp HyperSpec y Practical Common Lisp son tus amigos! –

+2

En otras palabras, 'with-open-file' hace todo el trabajo de' abrir' y 'cerrar' y' let'. –

8

¿Dónde están los problemas?

(defun get-file (filename) 
    (let ((x (open filename))) 
    (when x 
     (loop for line = (read-line x nil) 
      while line 
      do (list line))) ; <-- you are not collecting, just doing 
    (close x)))     ; <- the function returns the value of CLOSE 

(defun get-file (filename) 
    (let ((x (open filename :if-does-not-exist nil)) 
     (contents (list nil))) 
    (when x 
     (loop for line = (read-line x nil) 
      while line 
      do (cons contents line))) ; <-- again, the cons goes nowhere 
    (close x) contents))    ; <-- CONTENTS has never been changed 

(defun get-file (filename) 
    (let ((x (open filename :if-does-not-exist nil)) 
     (contents nil)) 
    (when x 
     (loop for line = (read-line x nil) 
      while line 
      do (append contents line))) ; <- again the result goes nowhere 
    (close x) contents))     ; <-- CONTENTS has never been changed 

DO simplemente ejecutará algo para los efectos secundarios.

COLLECT recopilará el resultado y el LOOP devolverá una lista de valores recopilados al salir.

Como ya se mencionó, use WITH-OPEN-FILE en lugar de OPEN/CLOSE. WITH-OPEN-FILE cerrará el archivo al salir del alcance dinámico. No solo por una salida normal, sino también por condiciones de error usando UNWIND-PROTECT.

Si quiere leer el contenido de un archivo, puede usar READ-SEQUENCE. Con los problemas usuales. Por ejemplo, cuando lee un archivo ASCII como texto en una cadena, la cadena puede ser más corta que el archivo. Por ejemplo, Common Lisp representará internamente CRLF con un solo carácter, en plataformas donde CRLF es nueva línea. Otro ejemplo: en implementaciones que admiten Unicode, el código UTF-8 en el archivo se puede reemplazar por un solo carácter.

+0

+1 para describir los errores! –

Cuestiones relacionadas