我想知道在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