2016-06-12 83 views
2

我正在使用一个Java包输出文本到控制台,我需要捕获一个字符串中的文本,但我不知道如何做到这一点。从查看Clojure文档看来,我所要做的就是将这个java调用封装在with-out-str中,但这对我不起作用。在Clojure捕获系统/出

最少的代码示例:如果我尝试

(with-out-str 
(.println (System/out) "foo")) 

我希望能获得与“foo”值的字符串,但它仍然输出到控制台。我究竟做错了什么?

回答

6

Java的System.out.println(...)PrintStream实例println方法的调用。你需要用自己的实例来代替System.out流和捕获其内容:

(import [java.io ByteArrayOutputStream PrintStream]) 

(def out-buffer (java.io.ByteArrayOutputStream.)) 

(System/setOut (java.io.PrintStream. out-buffer true "UTF-8")) 

(defn out-str [] 
    (.toString out-buffer "UTF-8")) 

在REPL小心,但因为它使用System.out打印结果,所以当你更换全球范围内,它会破坏你的REPL实例。

你甚至可以编写一个宏,将捕获System.out的内容,然后恢复原来的PrintStream实例:

(defmacro with-system-out-str [& body] 
    `(let [out-buffer# (ByteArrayOutputStream.) 
     original-out# System/out 
     tmp-out# (PrintStream. out-buffer# true "UTF-8")] 
    (try 
     (System/setOut tmp-out#) 
     [email protected] 
     (finally 
     (System/setOut original-out#))) 
    (.toString out-buffer# "UTF-8"))) 

(with-system-out-str 
    (.println System/out "Hi")) 
;; => "Hi\n" 
0

您可以将输出保存到文件中,然后读取文件的内容。

(def foo-file (clojure.java.io/writer "foo.txt")) 

(binding [*out* foo-file] 
    (println "Foo, bar.")) 

(println "Slurp: " (slurp "foo.txt"))