使用Clojure下载和读取内存中的压缩CSV文件需要帮助



我有一个外部站点,我想从中下载一个压缩的CSV文件。目前,我正在下载解压缩的文件,将其保存到磁盘,然后解压缩,将解压缩的文件保存到磁盘上,然后用CSV阅读器读取解压缩的文件。这个过程中很多无用的步骤都可以修剪掉,我就这样做了

这个惊人的答案帮助我振作起来。我试图使用链接到那里的第一个选项(GZIPInputStream(,但我得到了一个";不是GZIP格式";错误,所以我想我必须选择第二个选项。

这是我当前的代码,它做了我想做的事情:

(defn download-zipped-stream!
(:body (clj-http.client/get "www.example.com" {:as :stream})))
(with-open
[stream (ZipInputStream. download-zipped-stream!)]
(.getNextEntry stream)
(doall (clojure.data.csv/read-csv (clojure.java.io/reader stream) :separator ;)))

我真的是通过反复试验才做到这一点的。关于这段代码,我主要想改变/理解三件事。

  1. 理想情况下,我想把我的代码分成两部分:一部分是下载和解压缩内容,返回流-原因是我想稍后决定是否直接将其作为csv读取,或者写入磁盘(我不想失去这个选项,因为在开发过程中,读取预先下载的csv文件比每次下载大内容要容易得多(。事实证明,如果我试图访问with-open调用之外的流,我会得到一个"0";流关闭";错误(据我所知,这完全有道理(。

  2. 在上面的代码中,我必须调用这个.getNextEntry,否则我会得到一个空列表。作为一个努力编写函数式代码的人,这让我很困扰,因为据我所知,我在这里处理的是状态——我的流对象看起来是可变的,这是我真的不想要的。难道没有办法绕过这一步,然后直接放弃它吗?

  3. 我试图直接在stream对象上调用read-csv方法,但read-csv显然不知道如何处理ZipInputStreams。看到这一点,我只是满怀希望地在中间抛出了一个io/reader调用,结果成功了。不过,我不知道这是否是最好的方法。这是正确的吗?

我对Clojure还很陌生,而且我对Java总体上一无所知,所以,正如你所看到的,我对这些流对象的了解非常有限。我试着用Java读一些关于它的东西,但我放弃了,因为我不确定其中有多少对学习Clojure的人有用,所以任何建议都会受到赞赏。

我认为你的方法是正确的。建议考虑:

  1. 考虑使用wget手动将*.csv.gz文件下载到本地磁盘。然后,只需打开该本地文件,而不用clj-http.client/get

  2. 我没有玩过太多ZipInputStream,但如果似乎需要使用.getNextEntry(),那就去吧。

  3. read csv的示例显示使用阅读器访问输入文件,因此这是预期的行为。

  4. 这个模板项目展示了我喜欢如何组织一个Clojure项目&源代码。请务必仔细阅读所提供的文件清单。

  5. 不要忘记使用cljdoc.org来查找Clojure库API文档。例如,有关data.csv.,请参阅API文档


更新

你可能还想复习一下这个答案。

使用https://github.com/techascent/tech.ml.dataset可选带有https://scicloj.github.io/tablecloth/index.html(TMD的类似dplyr的api(

还具有速度极快的优势,能够处理内存中无法容纳的数据集,talk SQL,Arrow等。在这里加入关于它的对话:https://clojurians.zulipchat.com/#narrow/stream/151924-数据科学/主题/技术.2Eml.2Edataset

最新更新