使用clojure-csv.core解析一个巨大的csv文件

5 csv clojure bigdata

到目前为止,我有:

(: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)


Mar*_*her 7

我知道这已经得到了解答,但是这里有一个类似于@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数据分析手册