需要帮助使用 Clojure 下载和读取内存中的压缩 CSV 文件
Need help downloading and reading a zipped CSV file in memory with Clojure
我有一个外部站点,我想从中下载压缩的 CSV 文件。目前,我正在下载解压缩的文件,将其保存到磁盘,然后解压缩,将解压缩的文件保存到磁盘,然后使用 CSV reader 读取解压缩的文件。这个过程中很多无用的步骤都可以被删掉,我一直在这样做。
帮助我继续前进。我尝试使用那里链接的第一个选项 (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 \;)))
我确实是通过反复试验得到的。关于这段代码,我主要想更改/理解三件事。
理想情况下,我想将我的代码分为两部分:一个是下载和解压缩内容,返回一个流——原因是我想稍后决定是否要阅读它直接作为 csv,或写入磁盘(我不想失去这个选项,因为在开发过程中,读取预下载的 csv 文件比每次下载大内容要容易得多)。事实证明,如果我尝试访问 with-open
调用之外的流,我会收到“流关闭”错误(据我所知,这是完全有道理的)。
在上面的代码中,我必须调用这个 .getNextEntry
,否则我会得到一个空列表。作为一个正在努力编写功能代码的人,这让我很困扰,因为据我所知,我在这里处理状态——我的流对象看起来是可变的,这是我真的不想要的。有没有一种方法可以绕过这一步并且直接没有它?
我试图直接在 stream
对象上调用 read-csv
方法,但是 read-csv
显然不知道如何处理 ZipInputStreams。看到这一点,我简单地希望在两者之间抛出一个 io/reader
调用,并且它起作用了。不过,我不知道这是否是最好的方法。正确吗?
我是 Clojure 的新手,一般来说我对 Java 一无所知,因此,如您所见,我对这些流对象的了解非常有限。我试图在 Java 中阅读有关它的一些内容,但我放弃了,因为我不确定其中有多少对学习 Clojure 的人有用,所以任何指针也很感激。
我认为您的方法是正确的。考虑的建议:
考虑使用 wget
手动将 *.csv.gz
文件下载到您的本地磁盘。然后,只需打开该本地文件而不是使用 clj-http.client/get
.
我没怎么玩过ZipInputStream,但如果觉得需要用.getNextEntry()
,就用吧。
read-csv 的示例显示使用 Reader 来访问输入文件,因此这是预期的行为。
This template project 展示了我喜欢如何组织 Clojure 项目和源代码。请务必仔细阅读所提供的文档列表。
别忘了utilize cljdoc.org for looking up Clojure library API docs. For example, see the API docs for data.csv。
更新
您可能还想查看 。
使用https://github.com/techascent/tech.ml.dataset optionally with https://scicloj.github.io/tablecloth/index.html(TMD 类似api 的dplyr)
还具有速度极快的优势,能够处理无法放入内存的数据集,会谈 SQL、Arrow 等。阿尔。在这里加入关于它的对话:
https://clojurians.zulipchat.com/#narrow/stream/151924-data-science/topic/tech.2Eml.2Edataset
我有一个外部站点,我想从中下载压缩的 CSV 文件。目前,我正在下载解压缩的文件,将其保存到磁盘,然后解压缩,将解压缩的文件保存到磁盘,然后使用 CSV reader 读取解压缩的文件。这个过程中很多无用的步骤都可以被删掉,我一直在这样做。
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 \;)))
我确实是通过反复试验得到的。关于这段代码,我主要想更改/理解三件事。
理想情况下,我想将我的代码分为两部分:一个是下载和解压缩内容,返回一个流——原因是我想稍后决定是否要阅读它直接作为 csv,或写入磁盘(我不想失去这个选项,因为在开发过程中,读取预下载的 csv 文件比每次下载大内容要容易得多)。事实证明,如果我尝试访问
with-open
调用之外的流,我会收到“流关闭”错误(据我所知,这是完全有道理的)。在上面的代码中,我必须调用这个
.getNextEntry
,否则我会得到一个空列表。作为一个正在努力编写功能代码的人,这让我很困扰,因为据我所知,我在这里处理状态——我的流对象看起来是可变的,这是我真的不想要的。有没有一种方法可以绕过这一步并且直接没有它?我试图直接在
stream
对象上调用read-csv
方法,但是read-csv
显然不知道如何处理 ZipInputStreams。看到这一点,我简单地希望在两者之间抛出一个io/reader
调用,并且它起作用了。不过,我不知道这是否是最好的方法。正确吗?
我是 Clojure 的新手,一般来说我对 Java 一无所知,因此,如您所见,我对这些流对象的了解非常有限。我试图在 Java 中阅读有关它的一些内容,但我放弃了,因为我不确定其中有多少对学习 Clojure 的人有用,所以任何指针也很感激。
我认为您的方法是正确的。考虑的建议:
考虑使用
wget
手动将*.csv.gz
文件下载到您的本地磁盘。然后,只需打开该本地文件而不是使用clj-http.client/get
.我没怎么玩过ZipInputStream,但如果觉得需要用
.getNextEntry()
,就用吧。read-csv 的示例显示使用 Reader 来访问输入文件,因此这是预期的行为。
This template project 展示了我喜欢如何组织 Clojure 项目和源代码。请务必仔细阅读所提供的文档列表。
别忘了utilize cljdoc.org for looking up Clojure library API docs. For example, see the API docs for data.csv。
更新
您可能还想查看
使用https://github.com/techascent/tech.ml.dataset optionally with https://scicloj.github.io/tablecloth/index.html(TMD 类似api 的dplyr)
还具有速度极快的优势,能够处理无法放入内存的数据集,会谈 SQL、Arrow 等。阿尔。在这里加入关于它的对话: https://clojurians.zulipchat.com/#narrow/stream/151924-data-science/topic/tech.2Eml.2Edataset