双读取大CSV文件

问题描述:

我有一个大的CSV不会完全适合内存,我需要做很多工作。我是懒惰序列的新手,不知道如何解决这个问题。我试图将整个文件读入内存,然后解析它,我知道这是错误的。双读取大CSV文件

这里就是我想要做的事:

  1. 阅读标题行和以此为基础进行的事情。它在整个程序中使用。
  2. 阅读所有行并收集每列的汇总数据。
  3. 使用汇总数据转换原始数据并写入新文件。

有没有一种方法可以读取标题行并不断地使用它,而不会导致懒惰序列的“保持头部”问题,将整个事件保留在内存中?

我发现这个相关线程:using clojure-csv.core to parse a huge csv file

+0

逐行解析文件两次,行。第一遍收集您的摘要信息;在第二遍时执行转换并将结果逐行写入新文件。 – 2014-10-12 02:58:42

+0

我会用'let'来定义两个不同的符号还是重复使用同一个符号?为什么这样避免“头痛医头”? – user1559027 2014-10-12 06:45:15

+0

请查看我对句子问题的修订是否通过询问具体结果的可能性而将本文从“主要基于意见”移出。 – user1559027 2014-10-13 23:20:11

Clojure的负责清除本地绑定的,所以一旦绑定不再将被使用,它会被清零,使之符合要求的供GC。所以,你的代码可能看起来是这样的:

(defn gather-summary [file] 
    (with-open [rdr (io/reader file)] 
     (let [lines (csv/read-csv rdr) 
      header (first lines)] 
      (reduce (fn [so-far row] 
        (if header 
        (inc so-far) 
        (dec so-far))) 
       0 
       (rest lines)))) 

(defn modify [summary file] 
    ;similar to gather 
    ) 

(defn process [file] 
    (let [summary (gather-summary file)] 
     (modify summary file))) 

header不成立的头,因为它只是第一个元素,它不具有任何裁判线的其余部分。

lines在调用(rest lines)后没有使用,所以Clojure会清除它。

reduce作品上递归的方式,所以Clojure中也需要的not holding the head in that case

+0

考虑使用术语'binding'而不是'var',因为'var'是Clojure中的一种特定类型的数据,它是可变的,并且几乎总是全局的。 – noisesmith 2014-10-12 21:31:03

+0

谢谢!改变了它。 – DanLebrero 2014-10-12 22:23:50

+0

所以这个解决方案的关键是使用该文件封装读取文件内的文件?这样,当函数返回时,它知道释放底层序列?我一直在相同的'let'范围内声明文件序列并将其作为参数传递给所有函数,但这似乎是我的主要设计缺陷。 – user1559027 2014-10-13 23:23:33