Mic*_*ent 265
假设我们这里只做文本文件,而不是一些疯狂的二进制文件.
数字1:如何将整个文件读入内存.
(slurp "/tmp/test.txt")
Run Code Online (Sandbox Code Playgroud)
当它是一个非常大的文件时不推荐.
2号:如何逐行读取文件.
(use 'clojure.java.io)
(with-open [rdr (reader "/tmp/test.txt")]
(doseq [line (line-seq rdr)]
(println line)))
Run Code Online (Sandbox Code Playgroud)
该with-open
宏照顾读者在身体的一端封闭.reader函数强制将字符串(它也可以执行URL等)转换为BufferedReader
.line-seq
提供一个懒惰的seq.要求延迟seq的下一个元素导致从读取器读取的行.
请注意,从Clojure 1.7开始,您还可以使用传感器读取文本文件.
3号:如何写入新文件.
(use 'clojure.java.io)
(with-open [wrtr (writer "/tmp/test.txt")]
(.write wrtr "Line to be written"))
Run Code Online (Sandbox Code Playgroud)
再次,with-open
注意BufferedWriter
在身体的末端闭合.Writer将字符串强制转换为a BufferedWriter
,通过java interop使用:(.write wrtr "something").
您也可以使用spit
,相反slurp
:
(spit "/tmp/test.txt" "Line to be written")
Run Code Online (Sandbox Code Playgroud)
4号:在现有文件中附加一行.
(use 'clojure.java.io)
(with-open [wrtr (writer "/tmp/test.txt" :append true)]
(.write wrtr "Line to be appended"))
Run Code Online (Sandbox Code Playgroud)
与上面相同,但现在有附加选项.
或者spit
与之相反slurp
:
(spit "/tmp/test.txt" "Line to be written" :append true)
Run Code Online (Sandbox Code Playgroud)
PS:为了更明确地说明您正在读取和写入文件而不是其他内容,您可以先创建一个File对象,然后将其强制转换为BufferedReader
Writer或Writer:
(reader (file "/tmp/test.txt"))
;; or
(writer (file "tmp/test.txt"))
Run Code Online (Sandbox Code Playgroud)
文件功能也在clojure.java.io中.
PS2:有时能够看到当前目录(所谓的".")是很方便的.您可以通过两种方式获得绝对路径:
(System/getProperty "user.dir")
Run Code Online (Sandbox Code Playgroud)
要么
(-> (java.io.File. ".") .getAbsolutePath)
Run Code Online (Sandbox Code Playgroud)
Pau*_*aul 32
如果文件适合内存,你可以用slurp和spit读取和写入:
(def s (slurp "filename.txt"))
Run Code Online (Sandbox Code Playgroud)
(现在包含文件的内容为字符串)
(spit "newfile.txt" s)
Run Code Online (Sandbox Code Playgroud)
如果它不退出并写入文件内容,则会创建newfile.txt.如果你想附加到文件,你可以做
(spit "filename.txt" s :append true)
Run Code Online (Sandbox Code Playgroud)
要按行读取或写入文件,您将使用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!"
Run Code Online (Sandbox Code Playgroud)
请注意,slurp/spit与读取器/写入器示例之间的区别在于文件在后者中保持打开(在let语句中)并且读取和写入被缓冲,因此在重复读取/写入文件时更有效.
以下是更多信息:slurp spit clojure.java.io Java的BufferedReader Java的编写器
关于问题2,人们有时希望将流作为第一类对象返回.为了把它作为一个懒惰的序列,并且仍然在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)))
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
67929 次 |
最近记录: |