gpt4 book ai didi

ruby - 使用 ruby​​ 流式传输和解压缩大型 csv 文件

转载 作者:数据小太阳 更新时间:2023-10-29 06:53:26 24 4
gpt4 key购买 nike

我遇到问题,我需要下载、解压缩,然后逐行处理一个非常大的 CSV 文件。我认为让您了解文件有多大很有用:

  • big_file.zip ~700mb
  • big_file.csv ~23gb

这是我希望发生的一些事情:

  • 解压缩前不必下载整个文件
  • 在解析 csv 行之前不必解压缩整个文件
  • 在执行所有这些操作时不要占用太多内存/磁盘

我不知道这是否可能。这是我的想法:

require 'open-uri'
require 'rubyzip'
require 'csv'

open('http://foo.bar/big_file.zip') do |zipped|
Zip::InputStream.open(zipped) do |unzipped|
sleep 10 until entry = unzipped.get_next_entry && entry.name == 'big_file.csv'
CSV.foreach(unzipped) do |row|
# process the row, maybe write out to STDOUT or some file
end
end
end

这是我所知道的问题:

  • open-uri 读取整个响应并将其保存到一个 Tempfile 中,这对于这种大小的文件是不利的。我可能需要直接使用 Net::HTTP,但我不确定如何做到这一点并仍然获得 IO
  • 我不知道下载速度有多快,也不知道 Zip::InputStream 是否按照我展示的方式工作。当文件还没有全部存在时,它可以解压缩一些文件吗?
  • CSV.foreach 能否与 ruby​​zip 的 InputStream 一起使用?它的行为是否足够像 File 以能够解析出行?如果它想读取但缓冲区是空的,它会崩溃吗?

我不知道这是否是正确的方法。也许一些 EventMachine 解决方案会更好(虽然我以前从未使用过 EventMachine,但如果它对这样的事情更有效,我完全赞成)。

最佳答案

我发布这个问题已经有一段时间了,如果其他人遇到它,我认为可能值得分享我的发现。

  1. 对于我处理的行数,Ruby 的标准库 CSV 太慢了。我的 csv 文件非常简单,我不需要所有这些东西来处理带引号的字符串或强制类型转换。只需使用 IO#gets 然后用逗号分隔行就容易多了。
  2. 我无法将整个内容从 http 传输到 Zip::Inputstream 到包含 csv 数据的某些 IO。这是因为 zip file structure在文件末尾有中央目录结尾 (EOCD)。这是提取文件所必需的,因此从 http 流式传输文件似乎行不通。

我最终采用的解决方案是将文件下载到磁盘,然后使用 Ruby 的 open3 库和 Linux unzip 包从 zip 流式传输未压缩的 csv 文件。

require 'open3'

IO.popen('unzip -p /path/to/big_file.zip big_file.csv', 'rb') do |io|
line = io.gets
# do stuff to process the CSV line
end

unzip 上的 -p 开关将提取的文件发送到标准输出。 IO.popen 然后使用管道使其成为 ruby​​ 中的 IO 对象。效果很好。如果您想要额外的处理,您也可以将它与 CSV 一起使用,这对我来说太慢了。

require 'open3'
require 'csv'

IO.popen('unzip -p /path/to/big_file.zip big_file.csv', 'rb') do |io|
CSV.foreach(io) do |row|
# process the row
end
end

关于ruby - 使用 ruby​​ 流式传输和解压缩大型 csv 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23377263/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com