2014-04-29 13 views
6

जहाँ मैं डाउनलोड करने के लिए, अनज़िप लाइन द्वारा प्रक्रिया लाइन एक बहुत बड़ी CSV फ़ाइल की जरूरत है, और फिर मैं समस्या है के साथ बड़े csv फ़ाइल अनज़िप। मुझे लगता है कि आप इसका अंदाज़ा लगा बड़ी फाइल है देने के लिए उपयोगी होता है:स्ट्रीम और गहरे लाल रंग का

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

ये कुछ चीजें हैं मैं ऐसा करना चाहते हैं क्या है:

  • अनज़िप करने से पहले पूरी फ़ाइल डाउनलोड करने के लिए सीएसवी पंक्तियों को पार्सिंग से पहले पूरी फ़ाइल अनज़िप करने नहीं है नहीं है
  • 0,123,
  • बहुत अधिक स्मृति/डिस्क का उपयोग करते हुए यह सब

मुझे लगता है कि यदि संभव है या नहीं पता नहीं है कर रही है। यहाँ मैं क्या सोच रहा था:

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 तरह से मैं काम कर यह दिखाया है काम करता है। क्या यह फ़ाइल में से कुछ को अनजिप कर सकता है जब यह अभी तक नहीं है?
  • विल rubyzip के InputStream साथ CSV.foreach काम करता है? क्या यह File की तरह व्यवहार करता है कि यह पंक्तियों को पार करने में सक्षम होगा? अगर यह पढ़ना चाहता है तो क्या यह निकल जाएगा लेकिन बफर खाली है?

मुझे नहीं पता कि इनमें से कोई भी सही दृष्टिकोण है या नहीं। हो सकता है कि कुछ EventMachine समाधान बेहतर होगा (हालांकि मैंने पहले EventMachine उपयोग नहीं किया है, लेकिन अगर यह कुछ इस तरह के लिए बेहतर काम करता है, मैं इसके लिए सभी हूँ)।

+0

मुझे नहीं लगता कि ज़िप स्ट्रीमिंग की वजह से ज़िप स्ट्रीमिंग करने जा रहा है। यह शायद 'funzip' जैसा कुछ कर सकता है अगर ज़िप में केवल एक फ़ाइल थी (या जिसे मैं पहले चाहता था) लेकिन ऐसा नहीं है। – ZombieDev

उत्तर

6

थोड़ा समय के बाद से मैं इस प्रश्न पोस्ट हो गया है और इस मामले में किसी और को यह भर आता है मैंने सोचा कि यह साझा करने मैं क्या पाया लायक हो सकता है।

  1. पंक्तियों मैं रूबी के मानक पुस्तकालय CSV के साथ काम कर रहा था की संख्या के लिए बहुत धीमी गति से किया गया था। मेरी सीएसवी फ़ाइल इतनी सरल थी कि मुझे उद्धृत तारों से निपटने के लिए उन सभी चीजों की आवश्यकता नहीं थी या फिर भी जबरदस्त टाइप करें। यह IO#gets का उपयोग करना बहुत आसान था और फिर कॉमा पर लाइन को विभाजित करता था।
  2. मैं एक कुछ IO csv डेटा युक्त Zip::Inputstream लिए http से पूरी बात स्ट्रीम करने के लिए असमर्थ था। इसका कारण यह है zip file structure फ़ाइल के अंत में केंद्रीय निर्देशिका (EOCD) का अंत नहीं है। फाइल को निकालने के लिए इसकी आवश्यकता है ताकि इसे http से स्ट्रीम करना ऐसा प्रतीत नहीं होता है कि यह काम करेगा।

समाधान मैं के साथ जा रहा समाप्त हो गया डिस्क पर फ़ाइल डाउनलोड करें और फिर रूबी के open3 पुस्तकालय और लिनक्स unzip पैकेज का उपयोग जिप से असम्पीडित 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 स्विच 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 
संबंधित मुद्दे