输入/输出
Clojure提供了很少的方法来进行输入/输出的操作。因为我们在Clojure代码里面可以很轻松的使用java里面的I/O操作方法。但是?clojure.java.io 库使得使用java的I/O方法更加简单。
这些预定义的special symbols *in*
, *out*
以及 *err*
默认被设定成 stdin, stdout 以及 stderr 。如果要flush *out*
,里面的输出,使用 (flush)
方法,效果和 (.flush *out*)
一样。当然这些symbol的binding是可以改变的。比如你可以把输出重定向到 " my.log
"文件里面去。 看下面的例子:
(binding [*out* (java.io.FileWriter. "my.log")]
...
(println "This goes to the file my.log.")
...
(flush))
print
可以打印任何对象的字符串表示到out,并且在两个对象之间加一个空格。
println
函数和 print
类似, 但是它会在最后加一个newline符号。默认的话它还会有一个flush的动作。这个默认动作可以通过把 special symbol *flush-on-newline*
设成 false
来取消掉。
newline
函数写一个newline符号 *out*
流里面去。 在调用 print
函数后面手动调用 newline
和直接调用 println
的效果是一样的。
pr
与 prn
是和 print
与 println
想对应的一对函数, 但是他们输出的形式可以被 Clojure reader去读取。它们对于把Clojure的对象进行序列化的时候比较有用。默认情况下它们不会打印数据的元数据。可以通过把 special symbol *print-meta*
设置成 true
来调整这个行为。
下面的例子演示了我们提到的四个打印方法。注意使用print和pr输出的字符串的不同之处。
(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}
所有上面讨论的几个打印函数都会在它们的参数之间加一个空格。你可以通过 str
函数来预先组装好要打印的字符串来避免这个行为, 看下面例子:
(println "foo" 19) ; -> foo 19
(println (str "foo" 19)) ; -> foo19
print-str
, println-str
, pr-str
以及 prn-str
函数 print
, println
, pr
跟 prn
类似, 只是它们返回一个字符串,而不是把他们打印出来。
printf
函数和 print
类似。但是它接受一个format字符串。 format
函数和 printf
, 类似,只是它是返回一个字符串而不是打印出来。
宏 with-out-str
把它的方法体里面的所有输出汇总到一个字符串里面并且返回。
with-open
可以自动关闭所关联的连接(.close)方法, 这对于那种像文件啊,数据库连接啊,比较有用,它有点像C#里面的using语句。
line-seq
接受一个 java.io.BufferedReader
参数,并且返回一个LazySeq, 这个LazySeq包含所有的一行一行由BufferedReader读出的文本。返回一个LazySeq的好处在于,它不用马上读出文件的所有的内容, 这会占用太大的内存。相反, 它只需要在需要使用的时候每次读一行出来即可。
下面的例子演示了 with-open
和 line-seq
的用法。 它读出一个文件里面所有的行, 并且打印出包含某个关键字的那些行。
(use '1)
(defn print-if-contains [line word]
(when (.contains line word) (println line)))
(let [file "story.txt"
word "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))))
slurp
函数把一个文件里面的所有的内容读进一个字符串里面并且返回。 spit
把一个字符串写进一个文件里面然后关闭这个文件。
这篇文章只是大概过了一下clojure的io里面提供了哪些函数来进行I/O操作。大家可以看下clojure源文件: clojure/java/io.clj
以了解其它一些函数。