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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在clojure中读取stdin(* in *)中的行相关的知识,希望对你有一定的参考价值。

我正在编写我的第一个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中进行常规文件处理的例子?

答案

尝试在*in*中包装java.io.BufferedReader。并且还使用doseq而不是doall,正如devstopfix指出:

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

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

另一答案

您应该使用doseq而不是doall

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

doall

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

doseq

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

另一答案

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

另一答案

对于相当小的输入,以下也可以工作:

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

或者,按行拆分:

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

以上是关于如何在clojure中读取stdin(* in *)中的行的主要内容,如果未能解决你的问题,请参考以下文章

在阅读之前清除/清除System.in(stdin)

Clojure 懒惰地从文件中读取随机行

如何从标准输入读取 dask 数据帧?

如何正确读取 Clojure 中的 RandomAccessFile?

如何使用assoc-in更新地图中的多个值? (Clojure的)

如何在脚本中读取stdin?