2010-09-28 7 views
6

Ich möchte den Inhalt einer Datei in eine Liste einlesen. Einige meiner bisherigen Versuche waren -Wie kann ich den Inhalt einer Datei in Lisp in einer Liste lesen?

(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)) 

Keiner von diesen funktioniert. Kann mir jemand einen Weg sagen? Oder noch besser - wie man alle Inhalte in ein Array bringt?

Antwort

14

Wie wäre es

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

(mit-open-Datei (f Dateiname) Warum haben Sie eine f vor Dateinamen dort? Was macht eine Sammelleitung? Und wie arbeitet das mit der Linie am Ende zusammen? – Sterling

+3

'with-open-file' öffnet die Datei' filename' und verknüpft den Stream mit 'f'. "Sammeln" sammelt die verschiedenen Werte von "Zeile" in einer Liste, bis die "Weile" "Null" ist. Die Common Lisp HyperSpec und Practical Common Lisp sind deine Freunde! –

+2

Mit anderen Worten, 'with-open-file' erledigt alle Arbeiten von' open' und 'close' und die' let'. –

8

Wo sind die Probleme?

(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 wird nur etwas für Nebenwirkungen ausführen.

COLLECT sammelt das Ergebnis und LOOP gibt beim Beenden eine Liste der gesammelten Werte zurück.

Wie bereits erwähnt, verwenden Sie WITH-OPEN-FILE statt OPEN/CLOSE. WITH-OPEN-FILE schließt die Datei beim Verlassen des dynamischen Bereichs. Nicht nur von einem normalen Ausgang, sondern auch bei Fehlerbedingungen mit UNWIND-PROTECT.

Wenn Sie den Inhalt einer Datei lesen möchten, können Sie READ-SEQUENCE verwenden. Mit den üblichen Problemen. Wenn Sie beispielsweise eine ASCII-Datei als Text in eine Zeichenfolge lesen, ist die Zeichenfolge möglicherweise kürzer als die Datei. Zum Beispiel repräsentiert Common Lisp intern CRLF mit einem einzelnen Zeichen auf Plattformen, auf denen CRLF Newline ist. Ein weiteres Beispiel: In Unicode-unterstützenden Implementierungen kann der UTF-8-Code in der Datei durch ein einzelnes Zeichen ersetzt werden.

+0

+1 für die Beschreibung der Fehler! –

Verwandte Themen