Clojure:逐行读取edn文件

时间:2016-04-14 09:58:29

标签: clojure readfile

我在文件(种类)中写了类似的数据

{:a 25 :b 28}
{:a 2 :b 50}
...

我希望这些地图有一个懒惰的序列。

大约有4千万行。我也可以写10000块,但我不会改变写入函数的方式(mapcat而不是map

为了阅读它,我写了

(with-open [affectations (io/reader "dev-resources/affectations.edn")]
  (map read-string affectations))

问题在于Clojure告诉

Don't know how to create ISeq from : java.io.BufferedReader

老实说,我对java.io名称空间一无所知。 我想在文件中有一个懒惰的数据序列,但我不知道如何将流转换为字符串,然后是集合。

有什么想法吗?

这是read-line吗?

由于

1 个答案:

答案 0 :(得分:2)

您正在将java.io.BufferedReader传递给map,而map则需要一个seq。

您需要使用line-seq从文件中生成(懒惰)seq行:

(with-open [affectations (io/reader "dev-resources/affectations.edn")]
  (map read-string (lazy-seq affectations)))

请记住,您需要对从其范围内的with-open中打开的资源中读取的数据强制所有副作用,否则您将收到错误。

一种选择是强制从文件中强制输出整个文本行,并使用doall返回它。但是,此解决方案可以将所有数据读入内存,这看起来并不实用。

我猜你需要为文件中的每一行执行一些逻辑,而你不需要将所有这些已解析的集合保存在内存中。在这种情况下,您可以将表示该逻辑的函数传递给您处理文件的函数处理:

(defn process-file [filename process-fn]
  (with-open [reader (io/reader filename)]
    (doseq [line (line-seq reader)]
      (-> line
        (read-string)
        (process-fn)))))

此功能会逐行读取您的文件,并使用read-string单独转换每个文件并调用process-fn功能。 process-file将返回nil