在clojure中将大文件写入磁盘

时间:2015-10-20 18:50:17

标签: csv clojure

我有一个返回大量行的SQL查询。我想将查询结果保存到磁盘上的csv文件中。但是,因为有很多行,所以在sql查询聚合所有行之前我的内存耗尽。

看起来像这样,在查询部分失败:

(-> query format-transformer csv-writer)

1 个答案:

答案 0 :(得分:4)

我在#clojure irc频道的帮助下想出来了。你需要两个库:

(ns myproj.example
  (:require [[clojure.java.jdbc :as sql]
             [clojure.data.csv :as csv]]))

诀窍是在返回时处理每一行,然后丢弃它。 java jdbc库具有查询功能,该功能使用:row-fn:result-set-fn选项提供此功能。

(defn sql->csv  [title]
  (with-open [w (clojure.java.io/writer (str title ".csv") :append true)]
   (sql/query ds (second query)
             :row-fn (fn [row]
                       (csv/write-csv w  [(mapv str (vals row))]))
             :result-set-fn dorun)))

有趣的部分是:row-fn:result-set-fn

每次从查询返回一行时,都会调度:row-fn。每行都是{:column1 "data" :column2 "data2"}形式的地图。我们将map更改为write-csv可以使用的内容(嵌套向量):[(mapv str (:vals row)])。然后write-csv将它附加到你给它的文件中。

:result-set-fn对于不吹你的堆来说至关重要。通过将其设置为dorun,您可以告诉它在处理时丢弃头部。

这个特定的实现不提供列标题,这是留给读者的一个练习(我的公共论坛上发帖太尴尬了)。