У меня проблема, когда мне нужно скачать, разархивировать, а затем обработать построчно очень большой файл CSV. Я думаю, полезно дать вам представление о том, насколько велик файл:
- big_file.zip ~ 700 МБ
- big_file.csv ~ 23 ГБ
Вот некоторые вещи, которые я хотел бы сделать:
- Не нужно загружать весь файл перед распаковкой
- Не нужно распаковывать весь файл перед разбором строк 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
работать сInputStream
rubyzip? Достаточно ли он ведет себя какFile
, чтобы разобрать строки? Не взбесится ли он, если захочет прочитать, но буфер пуст?
Не знаю, правильный ли это подход. Возможно, какое-то решение EventMachine было бы лучше (хотя я никогда раньше не использовал EventMachine, но если оно работает лучше для чего-то подобного, я полностью за).
funzip
, если бы в zip был только один файл (или тот, который я хотел, был первым), но это не тот случай. - person ZombieDev   schedule 30.04.2014