Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Capturing System/out in Clojure

Tags:

java

clojure

I'm working with a Java package that outputs text to the console and I need to capture that text in a string, but I'm not sure how to do this. From looking at the Clojure documentation it seemed that all I have to do is wrap the java call in with-out-str but that isn't working for me.

Minimal code example: if I try

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

I'm hoping to get a string with the value "foo", but it's still outputting to the console instead. What am I doing wrong?

like image 344
stuwest Avatar asked Oct 27 '25 20:10

stuwest


1 Answers

Java's System.out.println(...) is a call to println method of PrintStream instance. You need to replace the System.out stream with your own instance and capture its content:

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

Watch out in the REPL though because it uses System.out to print the results so when you replace it globally, it will break your REPL instance.

You can even write a macro that will capture the content of the System.out and then restore the original PrintStream instance:

(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#)
       ~@body
       (finally
         (System/setOut original-out#)))
     (.toString out-buffer# "UTF-8")))

(with-system-out-str
  (.println System/out "Hi"))
;; => "Hi\n"
like image 100
Piotrek Bzdyl Avatar answered Oct 29 '25 09:10

Piotrek Bzdyl



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!