Zom*_*Dev 8 ruby csv io rubyzip net-http
我有问题需要下载,解压缩,然后逐行处理一个非常大的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
Run Code Online (Sandbox Code Playgroud)
这是我所知道的问题:
open-uri读取整个响应并将其保存到Tempfile这个大小的文件中.我可能需要Net::HTTP直接使用,但我不知道该怎么做,仍然得到一个IO.Zip::InputStream我的工作方式是否正常.当它不是全部时,它可以解压缩一些文件吗?CSV.foreach用rubyzip的工作InputStream?它的行为是否足以File解析行?如果它想要读取但缓冲区是空的,它会变得怪异吗?我不知道这是否是正确的做法.也许一些EventMachine解决方案会更好(虽然我以前从未使用过EventMachine,但如果它对这样的东西更好用,我就是为了它).
Zom*_*Dev 11
自从我发布这个问题已经有一段时间了,如果有人遇到它,我认为可能值得分享我发现的东西.
CSV太慢了.我的csv文件很简单,无论如何我都不需要处理引用的字符串或类型强制.只使用它IO#gets然后在逗号上拆分行就容易得多.Zip::Inputstream到IO包含csv数据的内容.这是因为zip文件结构在文件末尾具有中央目录结束(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
Run Code Online (Sandbox Code Playgroud)
在-p上解压开关所抽取的文件发送到stdout.IO.popen然后使用管道将其作为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
Run Code Online (Sandbox Code Playgroud)