2010-09-28 2 views
6

Je souhaite lire le contenu d'un fichier dans une liste. Certaines de mes tentatives à ce jour ont été -Comment puis-je lire le contenu d'un fichier dans une liste 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)) 

Aucune de ces tentatives. Quelqu'un peut-il me dire un moyen? Ou encore mieux - comment mettre tout le contenu dans un tableau?

Répondre

14

Que diriez-vous

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

(avec-fichier ouvert (f nom) Pourquoi avez-vous un f avant le nom de fichier là-bas? que fait la ligne de collection? Et comment cela collabore-t-il avec la ligne à la fin? – Sterling

+3

'with-open-file' ouvre le fichier appelé' filename' et associe le flux à 'f'. 'collectioning 'recueille les différentes valeurs de' line' dans une liste, jusqu'à ce que 'while' soit' nil'. Le Common Lisp HyperSpec et le Common Lisp pratique sont vos amis! –

+2

En d'autres termes, 'with-open-file' fait tout le travail de' open' et 'close' et le' let'. –

8

Où sont les problèmes?

(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 va simplement exécuter quelque chose pour les effets secondaires. COLLECT va collecter le résultat et la boucle retournera alors une liste de valeurs collectées à la sortie.

Comme déjà mentionné, utilisez WITH-OPEN-FILE au lieu de OPEN/CLOSE. WITH-OPEN-FILE fermera le fichier en quittant la portée dynamique. Pas seulement à partir d'une sortie normale, mais aussi lors de conditions d'erreur avec UNWIND-PROTECT.

Si vous souhaitez lire le contenu d'un fichier, vous pouvez utiliser READ-SEQUENCE. Avec les problèmes habituels. Par exemple, lorsque vous lisez un fichier ASCII en tant que texte dans une chaîne, la chaîne peut être plus courte que le fichier. Par exemple, Common Lisp représentera CRLF en interne avec un seul caractère, sur les plates-formes où CRLF est en nouvelle ligne. Autre exemple: dans les implémentations supportant Unicode, le code UTF-8 du fichier peut être remplacé par un seul caractère.

+0

+1 pour décrire les erreurs! –

Questions connexes