我想知道在clojure 1.3中讀取和寫入文件的「推薦」方式。在Clojure 1.3中,如何讀取和寫入文件
- 如何讀取整個文件
- 如何通過線
- 讀取文件中的行如何寫一個新的文件
- 如何將行添加到現有的文件
我想知道在clojure 1.3中讀取和寫入文件的「推薦」方式。在Clojure 1.3中,如何讀取和寫入文件
假設我們只是做文字這裏,而不是文件的一些瘋狂的二進制的東西。
編號1:如何將整個文件讀入內存。
(slurp "/tmp/test.txt")
當它是一個非常大的文件時不推薦。
2號:如何逐行讀取文件。
(use 'clojure.java.io)
(with-open [rdr (reader "/tmp/test.txt")]
(doseq [line (line-seq rdr)]
(println line)))
with-open
的宏負責讀者在所述主體的端部封閉。閱讀器功能強制一個字符串(它也可以做一個URL等)到BufferedReader
。 line-seq
提供了一個懶惰的seq。要求懶惰seq結果的下一個元素成爲從閱讀器讀取的行。
請注意,從Clojure 1.7開始,您還可以使用transducers來閱讀文本文件。
編號3:如何寫入新文件。
(use 'clojure.java.io)
(with-open [wrtr (writer "/tmp/test.txt")]
(.write wrtr "Line to be written"))
再次,with-open
照顧該BufferedWriter
在所述主體的端部封閉。作家強制將字符串轉換成BufferedWriter
,您使用使用通過Java的互操作:(.write wrtr "something").
您還可以使用spit
的slurp
相反:
(spit "/tmp/test.txt" "Line to be written")
4:即行追加到現有文件。
(use 'clojure.java.io)
(with-open [wrtr (writer "/tmp/test.txt" :append true)]
(.write wrtr "Line to be appended"))
與上面相同,但現在帶有附加選項。
與spit
再或者,的slurp
相反:
(spit "/tmp/test.txt" "Line to be written" :append true)
PS:更明確的事實,你是讀取和寫入文件,而不是別的東西,你可以先創建一個文件對象,然後強迫它變成一個BufferedReader
或作家:
(reader (file "/tmp/test.txt"))
;; or
(writer (file "tmp/test.txt"))
文件功能也在clojure.java.io。
PS2:有時可以很方便地看到當前目錄(如「。」)是什麼。你可以在兩種方式的絕對路徑:
(System/getProperty "user.dir")
或
(-> (java.io.File. ".") .getAbsolutePath)
非常感謝您的詳細解答。 我很高興在1.3中瞭解文件IO(文本文件)的推薦方式。 似乎已經有關文件的一些庫IO (clojure.contrb.io,clojure.contrib.duck流 並直接使用Java的BufferedReader的InputStreamReader的FileInputStream一些例子) 這讓我更加混亂。 此外幾乎沒有關於Clojure 1.3的信息 特別是日語(我的自然語言) 謝謝。 –
嗨快樂聖,TNX接受我的答案!爲了您的信息,clojure.contrib.duck-streams現在已被棄用。這可能會增加混亂。 –
非常豐富。謝謝。 – octopusgrabbus
如果文件適合內存,您可以使用slurp和spit進行讀寫:
(def s (slurp "filename.txt"))
(現S包含一個文件的內容作爲一個字符串)
(spit "newfile.txt" s)
這將創建newfile.txt如果它不退出,並寫入文件內容。 如果要附加到文件中,你可以做
(spit "filename.txt" s :append true)
要讀取或寫入文件面向行,你會使用Java的讀者和作家。它們被包裹在命名空間clojure.java.io:
(ns file.test
(:require [clojure.java.io :as io]))
(let [wrtr (io/writer "test.txt")]
(.write wrtr "hello, world!\n")
(.close wrtr))
(let [wrtr (io/writer "test.txt" :append true)]
(.write wrtr "hello again!")
(.close wrtr))
(let [rdr (io/reader "test.txt")]
(println (.readLine rdr))
(println (.readLine rdr)))
; "hello, world!"
; "hello again!"
需要注意的是啜食/吐和讀/寫器實例之間的區別在於,文件保持打開狀態(在咱們語句)在後者和讀取和寫入被緩衝,因此在反覆讀取/寫入文件時效率更高。
下面是詳細信息:slurpspit clojure.java.io Java's BufferedReader Java's Writer
關於第二個問題,人們有時要行的流返回第一類對象。爲了得到這個作爲一個懶惰的序列,並仍然在文件EOF自動關閉,我使用這個功能:
(use 'clojure.java.io)
(defn read-lines [filename]
(let [rdr (reader filename)]
(defn read-next-line []
(if-let [line (.readLine rdr)]
(cons line (lazy-seq (read-next-line)))
(.close rdr)))
(lazy-seq (read-next-line)))
)
(defn echo-file []
(doseq [line (read-lines "myfile.txt")]
(println line)))
我不認爲嵌套'defn'是意識形態Clojure。據我所知,你的'read-next-line'在你的'read-lines'函數之外是可見的。你可能使用了'(let [read-next-line(fn [] ...))''來代替。 – kristianlm
這是如何讀取整個文件。
如果該文件是在資源目錄,你可以這樣做:
(let [file-content-str (slurp (clojure.java.io/resource "public/myfile.txt")])
記住需要/使用clojure.java.io
(require '[clojure.java.io :as io])
(io/copy (io/file "/etc/passwd") \*out*\)
從谷歌第一個結果:HTTP: //lethain.com/reading-file-in-clojure/ – jcubic
這個結果是從2009年起,有些東西最近已經改變了。 – Sergey
確實。這個StackOverflow問題現在是Google的第一個結果。 – mydoghasworms