41
votes

I am writing my first clojure program, and want to read lines from stdin.

When I try this:

(doall (map #(println %) (line-seq *in*)))

I get this exception:

Exception in thread "main" java.lang.ClassCastException: clojure.lang.LineNumberingPushbackReader cannot be cast to java.io.BufferedReader (test.clj:0)

I get the same results in version 1.0 and 1.1

So how do I convert *in* into a seq I can iterate over? I would have thought that this is common enough that *in* itself would be iterable, but that does not work either - if I try to use it directly I get:

java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.LineNumberingPushbackReader (NO_SOURCE_FILE:0)

Also, are there any examples of doing general file handling in clojure?

4
replacing (map #(println %) (line-seq.. )) with just (map println (line-seq..)) could be nice - GabiMe

4 Answers

36
votes

Try wrapping *in* in a java.io.BufferedReader. And also use doseq instead of doall, as devstopfix pointed out:

(doseq [ln (line-seq (java.io.BufferedReader. *in*))]
   (println ln))

Note that line-seq is documented to require a BufferedReader as its source.

22
votes

Just a note that for anyone who wants to only read a single line, there's the read-line function.

22
votes

You should probably use doseq instead of doall:

(doseq [line (line-seq (java.io.BufferedReader. *in*))] 
    (println line))

doall:

Walks through the successive nexts of the seq, retains the head and returns it, thus causing the entire seq to reside in memory at one time.

doseq:

Does not retain the head of the sequence. Returns nil.

6
votes

For reasonably small inputs, the following would also work:

(let [input-string (slurp *in*)]
  (println input-string))

Or, splitting by lines:

(let [lines (clojure.string/split-lines (slurp *in*))]
  (println lines))