Ich möchte die "empfohlene" Art des Lesens und Schreibens einer Datei in Clojure 1.3 kennen.
- Wie man die ganze Datei liest
- So lesen Sie eine Datei Zeile für Zeile
- So schreiben Sie eine neue Datei
- So fügen Sie einer vorhandenen Datei eine Zeile hinzu
Antworten:
Angenommen, wir machen hier nur Textdateien und keine verrückten Binärdateien.
Nummer 1: Wie man eine ganze Datei in den Speicher liest.
Nicht zu empfehlen, wenn es sich um eine wirklich große Datei handelt.
Nummer 2: Wie man eine Datei Zeile für Zeile liest.
Das
with-open
Makro sorgt dafür, dass der Leser am Ende des Körpers geschlossen ist. Die Reader-Funktion zwingt eine Zeichenfolge (sie kann auch eine URL usw. ausführen) in eineBufferedReader
.line-seq
liefert eine faule seq. Das Anfordern des nächsten Elements der Lazy Seq führt dazu, dass eine Zeile vom Leser gelesen wird.Beachten Sie, dass Sie ab Clojure 1.7 auch Wandler zum Lesen von Textdateien verwenden können.
Nummer 3: Wie schreibe ich in eine neue Datei?
Auch hier ist darauf zu
with-open
achten, dass dasBufferedWriter
am Ende des Körpers geschlossen ist. Der Writer erzwingt einen String in einenBufferedWriter
, den Sie über Java Interop verwenden:(.write wrtr "something").
Sie könnten auch
spit
das Gegenteil von verwendenslurp
:Nummer 4: Fügen Sie eine Zeile an eine vorhandene Datei an.
Wie oben, jetzt jedoch mit Option zum Anhängen.
Oder nochmal mit
spit
dem Gegenteil vonslurp
:PS: Um genauer zu sagen, dass Sie in eine Datei lesen und schreiben und nicht in etwas anderes, können Sie zuerst ein Dateiobjekt erstellen und es dann in ein
BufferedReader
oder Writer zwingen :Die Dateifunktion befindet sich auch in clojure.java.io.
PS2: Manchmal ist es praktisch, das aktuelle Verzeichnis (also ".") Zu sehen. Sie können den absoluten Pfad auf zwei Arten erhalten:
oder
quelle
(with-open [rdr (reader "/tmp/test.txt")] (line-seq rdr))
AusbeutenIOException Stream closed
statt einer Sammlung von Linien. Was ist zu tun? Ich bekomme aber gute Ergebnisse mit der Antwort von @satyagraha.(with-open [rdr (reader "/tmp/test.txt")] (doall (line-seq rdr)))
doseq
Rückgabennil
zu traurigen Zeiten ohne Rückgabewert führen können.Wenn die Datei in den Speicher passt, können Sie sie mit Slurp und Spit lesen und schreiben:
(s enthält jetzt den Inhalt einer Datei als Zeichenfolge)
Dadurch wird newfile.txt erstellt, wenn es nicht beendet wird und den Dateiinhalt schreibt. Wenn Sie an die Datei anhängen möchten, können Sie dies tun
Um eine Datei zeilenweise zu lesen oder zu schreiben, verwenden Sie den Reader und Writer von Java. Sie werden in den Namespace clojure.java.io eingeschlossen:
Beachten Sie, dass der Unterschied zwischen Slurp / Spit und den Reader / Writer-Beispielen darin besteht, dass die Datei in letzteren offen bleibt (in den let-Anweisungen) und das Lesen und Schreiben gepuffert wird, was beim wiederholten Lesen / Schreiben in eine Datei effizienter ist.
Hier gibt es mehr Informationen: schlürfen spucken clojure.java.io Java BufferedReader Java Writer
quelle
In Bezug auf Frage 2 möchte man manchmal, dass der Zeilenstrom als erstklassiges Objekt zurückgegeben wird. Um dies als verzögerte Sequenz zu erhalten und die Datei auf EOF immer noch automatisch geschlossen zu haben, habe ich diese Funktion verwendet:
quelle
defn
ideomatisch ist. Ihrread-next-line
, soweit ich das verstehe, ist sichtbar außerhalb Ihrerread-lines
Funktion. Möglicherweise haben Sie(let [read-next-line (fn [] ...))
stattdessen eine verwendet.So lesen Sie die gesamte Datei.
Wenn sich die Datei im Ressourcenverzeichnis befindet, können Sie Folgendes tun:
Denken Sie daran, zu verlangen / zu verwenden
clojure.java.io
.quelle
quelle
Um eine Datei Zeile für Zeile zu lesen, müssen Sie nicht mehr auf Interop zurückgreifen:
Dies setzt voraus, dass Ihre Datendatei im Ressourcenverzeichnis gespeichert ist und dass die erste Zeile Header-Informationen enthält, die verworfen werden können.
quelle