How to: convert output stream into an input stream

1,773 views
Skip to first unread message

Trevor

unread,
Dec 15, 2011, 4:01:52 PM12/15/11
to Clojure
I have created an output stream, which appears to work fine, however
I get an error when trying to convert the output stream into an input
stream for use in ring:

('use [clojure.java.io :only [input-stream]])

=> (with-out-str (ofn var))
"it works!"

Now when I use ring:
{:body (input-stream (ofn var))}

java.lang.IllegalArgumentException: No implementation of method: :make-
input-stream of protocol: #'clojure.java.io/IOFactory found for class:
nil

Is there something special I need to do to convert output stream into
an input stream ?

Thanks,
Trevor

Shantanu Kumar

unread,
Dec 16, 2011, 4:29:01 AM12/16/11
to Clojure

Alan Malloy

unread,
Dec 16, 2011, 4:49:15 AM12/16/11
to Clojure
You can't really do this in a single thread without risking blocking.
But with another thread, it's fairly simple. For example, I do this in
my gzip-middleware, copying an InputStream through a pipe with GZIP
wrapping: https://github.com/amalloy/ring-gzip-middleware/blob/master/src/ring/middleware/gzip.clj#L10

I'm turning an input stream into another input stream, but you can do
something similar. It's a bit weird, because you're really *not*
attempting to convert an outputstream to an inputstream in your
example. You're calling a function that writes to stdout and returns
nil, and hoping that somehow a stream gets created. Really using with-
out-str is a reasonable approach here; just create a StringReader from
the resulting string.

But if you need asynchronicity, you can probably do something like

(let [pipe-in (PipedInputStream.)
pipe-out (PipedOutputStream. pipe-in)]
(future ; new thread to prevent blocking deadlock
(binding [*out* (PrintWriter. pipe-out)]
(ofn var)))
pipe-in)

This lets ofn run in another thread, writing its output to *out*,
which passes through the pipe and becomes an input stream for ring to
use.

Alan Malloy

unread,
Dec 16, 2011, 4:55:58 AM12/16/11
to Clojure
Edit: you should probably use with-open at some point, to make sure
you close the output writer. I copied pretty badly from my own
example :P. So more like:

(let [pipe-in (PipedInputStream.)]


(future ; new thread to prevent blocking deadlock

(with-open [out (-> pipe-in (PipedOutputStream.) (PrintWriter.))]
(binding [*out* out]
(do-whatever))))
pipe-in)

On Dec 16, 1:49 am, Alan Malloy <a...@malloys.org> wrote:
> You can't really do this in a single thread without risking blocking.
> But with another thread, it's fairly simple. For example, I do this in
> my gzip-middleware, copying an InputStream through a pipe with GZIP

> wrapping:https://github.com/amalloy/ring-gzip-middleware/blob/master/src/ring/...

Trevor

unread,
Dec 16, 2011, 12:16:17 PM12/16/11
to Clojure
This is great. Thanks for the help.
Reply all
Reply to author
Forward
0 new messages