如何在clojure中读取stdin(* in *)中的行

时间:2010-01-09 16:47:04

标签: clojure stdin

我正在编写我的第一个clojure程序,并希望从stdin读取行。

当我尝试这个时:

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

我得到了这个例外:

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

我在版本1.0和1.1中得到了相同的结果

那么如何将*in*转换为可以迭代的seq?我会认为这很常见,*in*本身可以迭代,但这也不起作用 - 如果我尝试直接使用它,我得到:

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

此外,是否有任何在clojure中进行常规文件处理的示例?

4 个答案:

答案 0 :(得分:26)

尝试在java.io.BufferedReader中换行*in*。并且使用doseq代替doall,正如devstopfix所指出的那样:

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

请注意,line-seq需要BufferedReader作为其来源。

答案 1 :(得分:21)

您应该使用doseq代替doall

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

doall

  

遍历seq的连续nexts,保留头部并返回它,从而导致整个seq一次驻留在内存中。

doseq

  

不保留序列的头部。返回nil。

答案 2 :(得分:20)

请注意,对于只想阅读一行的人来说,有read-line功能。

答案 3 :(得分:4)

对于相当小的输入,以下内容也适用:

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

或者,按行划分:

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