2016-06-12 5 views
2

Ich arbeite mit einem Java-Paket, das Text an die Konsole ausgibt, und ich muss diesen Text in einer Zeichenfolge erfassen, aber ich bin mir nicht sicher, wie das geht. Aus dem Blick auf die Clojure-Dokumentation schien es, dass ich nur den Java-Call in with-out-str einpacken musste, aber das funktioniert nicht für mich.Erfassen von System/out in Clojure

Minimal-Code Beispiel: Wenn ich versuche,

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

Ich hoffe auf eine Zeichenfolge mit dem Wert „foo“ zu bekommen, aber es ist immer noch statt an die Konsole ausgibt. Was mache ich falsch?

Antwort

6

Java System.out.println(...) ist ein Aufruf an println Methode der PrintStream Instanz. Sie müssen den System.out Strom mit dem eigenen Beispiel ersetzen und seinen Inhalt erfassen:

(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")) 

obwohl in den REPL Watch out, weil es System.out verwendet die Ergebnisse zu drucken, so dass, wenn Sie es global ersetzen, ist es Ihre REPL Instanz brechen .

Sie sogar ein Makro schreiben können, die den Inhalt des System.out und dann wieder auf die ursprüngliche PrintStream Instanz erfassen wird:

(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

Sie können die Ausgabe in eine Datei speichern und dann den Inhalt der Datei lesen.

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

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

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