到目前为止,我有:
(:require [clojure-csv.core :as csv])
(:require [clojure.java.io :as io]))
(def csv-file (.getFile (clojure.java.io/resource "verbs.csv")))
(defn process-csv [file]
(with-open [rdr (io/reader file)]
(csv/parse-csv rdr)))
Run Code Online (Sandbox Code Playgroud)
但我得到了java.io.IOException: Stream closed.我正在使用clojure-csv,它暴露了两种方法,我使用的第一种方法,parse-csv文档说:
Takes a CSV as a char sequence or string, and returns a lazy sequence of vectors of strings
Run Code Online (Sandbox Code Playgroud)
我想我知道的with-open是:懒惰,并且rdrin (csv/parse-csv rdr)))是csv文件的单行吗?
PS.我也想搜索文件,重复打开文件是否很昂贵(即使它是懒惰地阅读)并搜索整个内容?
noi*_*ith 11
with-open并不是懒惰,但如果你在里面做一些懒惰的事情with-open,如果懒惰的动作没有被强制进入范围内,你就会遇到问题with-open.需要做的是在退出with-open块之前强制所有延迟结果.
(defn process-csv [file]
(with-open [rdr (io/reader file)]
(doall (csv/parse-csv rdr))))
Run Code Online (Sandbox Code Playgroud)
该功能doall旨在确保实现整个延迟序列.
由于输入的大小,另一种可能性是安排自己关闭阅读器,然后将惰性用于其预期目的(仅在您需要时生成结果).
(defn find-results
[stream]
(for [record stream
:while (seq (first record))]
record))
(def rdr (io/reader "verbs.csv"))
(def csv (csv/parse-csv rdr))
(def results (doall (find-results csv)))
(.close rdr)
Run Code Online (Sandbox Code Playgroud)
我知道这已经得到了解答,但是这里有一个类似于@noisesmith的解决方案,它创建了一个显式的延迟序列,如果到达输入的末尾则会自动关闭.
如果您要懒惰地处理整个文件,这意味着您不必自己管理句柄,否则您会遇到打开句柄问题.
(defn lazy-read-csv
[csv-file]
(let [in-file (io/reader csv-file)
csv-seq (csv/read-csv in-file)
lazy (fn lazy [wrapped]
(lazy-seq
(if-let [s (seq wrapped)]
(cons (first s) (lazy (rest s)))
(.close in-file))))]
(lazy csv-seq)))
Run Code Online (Sandbox Code Playgroud)
这是来自Eric Rochester 出色的Clojure数据分析手册
| 归档时间: |
|
| 查看次数: |
4455 次 |
| 最近记录: |