File 逐行读取大文件
我正试图基于Clojure中的迭代为大文件编写阅读器。但是如何在Clojure中逐行返回字符串呢?我想做这样的东西: (println(dou_something(readFile(:file opts));处理并打印第一行File 逐行读取大文件,file,clojure,io,iterator,iteration,File,Clojure,Io,Iterator,Iteration,我正试图基于Clojure中的迭代为大文件编写阅读器。但是如何在Clojure中逐行返回字符串呢?我想做这样的东西: (println(dou_something(readFile(:file opts));处理并打印第一行 (println(dou_something(readFile(:file opts));处理并打印第二行 代码: 也许我不理解“逐行返回”是什么意思,但我建议您编写一个函数,它接受文件和处理函数,然后为大文件的每一行打印处理函数的结果。或者,更一般地说,让我们接受处理函数
(println(dou_something(readFile(:file opts));处理并打印第二行 代码:
也许我不理解“逐行返回”是什么意思,但我建议您编写一个函数,它接受文件和处理函数,然后为大文件的每一行打印处理函数的结果。或者,更一般地说,让我们接受处理函数和输出函数(默认为println),因此,如果我们不仅希望打印,还希望通过网络发送、保存到某个位置、发送到另一个线程,等等:
(defn process-file-by-lines
"Process file reading it line-by-line"
([file]
(process-file-by-lines file identity))
([file process-fn]
(process-file-by-lines file process-fn println))
([file process-fn output-fn]
(with-open [rdr (clojure.java.io/reader file)]
(doseq [line (line-seq rdr)]
(output-fn
(process-fn line))))))
所以
您还可以尝试从读卡器延迟读取,这与
line seq
返回的延迟字符串列表不同。中讨论了详细信息,但其要点如下:
(defn lazy-file-lines [file]
(letfn [(helper [rdr]
(lazy-seq
(if-let [line (.readLine rdr)]
(cons line (helper rdr))
(do (.close rdr) nil))))]
(helper (clojure.java.io/reader file))))
然后,您可以将映射到只会在必要时读取的行上。正如链接答案中的更多细节所讨论的,缺点是如果您直到文件末尾才读取,则(.close rdr)将永远不会运行,这可能会导致资源问题。请尝试doseq:
(defn readFile [file]
(with-open [rdr (clojure.java.io/reader file)]
(doseq [line (line-seq rdr)]
(println line))))
“回程线”是什么意思?您可以在某个atom中写入行,但所有逐行读取都将是毫无意义的—您的atom保留在内存中。只需让您的readFile接受处理函数并打印结果即可。即使您愿意,也无法关闭文件,因为描述符的作用域是局部的。如果您确实需要lazy seq,最好显式打开和关闭。
(defn lazy-file-lines [file]
(letfn [(helper [rdr]
(lazy-seq
(if-let [line (.readLine rdr)]
(cons line (helper rdr))
(do (.close rdr) nil))))]
(helper (clojure.java.io/reader file))))
(defn readFile [file]
(with-open [rdr (clojure.java.io/reader file)]
(doseq [line (line-seq rdr)]
(println line))))