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

Dav*_*rby 38 stdin clojure

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

当我尝试这个:

(doall (map #(println %) (line-seq *in*)))
Run Code Online (Sandbox Code Playgroud)

我得到这个例外:

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

我在版本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)
Run Code Online (Sandbox Code Playgroud)

另外,有没有在clojure中进行常规文件处理的例子?

seh*_*seh 29

尝试包裹*in*java.io.BufferedReader.并且还使用devstopfix指出doseq代替doall:

(doseq [ln (line-seq (java.io.BufferedReader. *in*))]
   (println ln))
Run Code Online (Sandbox Code Playgroud)

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

  • 此代码不起作用.我得到错误"doseq需要一个向量的绑定"尝试@devstopfix写道.它对我有用. (2认同)

dev*_*fix 22

您应该使用doseq而不是doall:

(doseq [line (line-seq (java.io.BufferedReader. *in*))] 
    (println line))
Run Code Online (Sandbox Code Playgroud)

doall:

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

剂量:

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


Mik*_*den 20

请注意,对于任何想要只阅读一行的人来说,都有读取线功能.


mru*_*cci 6

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

(let [input-string (slurp *in*)]
  (println input-string))
Run Code Online (Sandbox Code Playgroud)

或者,按行拆分:

(let [lines (clojure.string/split-lines (slurp *in*))]
  (println lines))
Run Code Online (Sandbox Code Playgroud)

  • @EricIhli,[`slurp`](https://clojuredocs.org/clojure.core/slurp) 读取*所有*可用的输入(直到 EOF,即文件末尾)。因此,如果有大量输入(例如,至少有很多兆字节或几千兆字节),那么您将在单个变量“输入字符串”中同时将所有输入加载到内存中。然后*之后*,您将立即打印出所有内容。如果您的系统中有足够的 RAM,并且您已使用告诉 Java 使用足够 RAM 的 Java 选项启动 Clojure,那么这将起作用,但您可能仍然需要等待一段时间才能开始看到打印输出。 (3认同)
  • 什么是“相当小”?为什么这仅适用于“相当小的”输入? (2认同)