由于调用Java易如反掌,Clojure仅仅提供了一个用于处理I/O操作的非常小的函数集合,但是clojure.java.io库中的这些函数使得调用Java中那些处理I/O的类变得更加方便。
Clojure中预定义了几个特殊形式的全局绑定变量*in*, *out* 和 *err*,分别对应于标准输入、输出和错误处理 。【(flush)】等价于【(.flush *out*)】,将输出缓冲中的内容刷到标注输出流*out*中。当然这些绑定变量都是可以改变的,比如向如下所示你可以把输出重定向到 "my.log
"文件里面去:
(binding [*out* (java.io.FileWriter. "my.log")]
...
(println "This goes to the file my.log.")
...
(flush))
print函数能够将代表任意数量对象的字符串打印到特殊形式*out*所代表流中,这些对象用空格隔开 (print obj1 obj2),打印结果也将用单个空格隔开,要忽略这些空格可以写成这种形式(print str(obj1 obj2))。
println函数在输出换行符号时默认将缓冲刷入*out*中,但可以将*flush-on-newline*全局变量为false改变这一行为。
newline函数打印一个换行符号到*out*流中,println等价于print+newline。pr和prn函数分别对应print和println,不同的是它们能够以一种Clojure读取器可读的形式进行输出,比较适合用于进行Clojure数据结构的序列化。默认情况下,pr和prn不会打印元数据,可以通过将*print-meta*设置为true改变这一默认行为。
以下示例将阐述上述提到的所有四种打印函数:
(let [obj1 "foo"
obj2 {:letter \a :number (Math/PI)}] ; a map
(println "Output from print:")
(print obj1 obj2)
(println "Output from println:")
(println obj1 obj2)
(println "Output from pr:")
(pr obj1 obj2)
(println "Output from prn:")
(prn obj1 obj2))
上述代码的输出如下:
Output from print:
foo {:letter a, :number 3.141592653589793}Output from println:
foo {:letter a, :number 3.141592653589793}
Output from pr:
"foo" {:letter \a, :number 3.141592653589793}Output from prn:
"foo" {:letter \a, :number 3.141592653589793}
rint-str, println-str, pr-str and prn-str函数分别和print, println, pr and prn一一对应,不同的将内容打印到一个返回的字符串中。
printf和format都是使用格式化的字符串作为参数,后者将结果打印到返回的字符串而非标准输出*out*中。
with-open宏很适合用来处理一些像文件和数据库连接的资源。它可以持有任何数量的对象绑定,当其函数体中的表达式都被调用之后这些对象的.close会被调用
line-seq函数接受一个java.io.BufferedReader对象并返回一个拥有这个对象中文本的行的懒惰序列。返回一个懒惰序列非常重要的意义是当其调用时不会真正读取所有的行,这会消耗不少内存。每向懒惰序列执行一次请求操作它都会读取一行数据。
下述代码结合使用with-open和line-seq,将从文件中读取所有行,并打印含有指定word的行:
(use '[clojure.java.io :only (reader)])
(defn print-if-contains [line word]
(when (.contains line word) (println line)))
(let [file "story.txt"
word "fur"]
; will print fur
; with-open will close the reader after
; evaluating all the expressions in its body.
(with-open [rdr (reader file)]
(doseq [line (line-seq rdr)] (print-if-contains line word))))
输出将如下所示:
#'user/print-if-contains
word "fur"]
; will print fur
nil
函数slurp读取整合文件的内容到一个字符串中并返回该字符串,而函数spit则写入一个字符串到给定的文件中,完事之后便关闭。
该文隔靴挠痒,仅仅谈到 Clojure内核和java.io库所提供的一些表层的东西,并没有深入,非常值得投入精力去通读clojure/java/io.clj,了解它所定义一些其它函数。