2009-11-20 5 views
8

के साथ ज़िप में एक बड़ी फ़ाइल को संपीड़ित करने के लिए मुझे जावा क्लास ZipOutputStream के माध्यम से एक बड़ी फ़ाइल (~ 450 Mbyte) को संपीड़ित करने की आवश्यकता है। यह बड़ा आयाम मेरे जेवीएम हीप स्पेस की "आउटऑफमेमरी" त्रुटि की समस्या का कारण बनता है। ऐसा इसलिए होता है क्योंकि "zos.write (...)" विधि सभी फ़ाइल सामग्री को संपीड़ित करने से पहले एक आंतरिक बाइट सरणी में संपीड़ित करने के लिए संग्रहीत करती है।जावा

  origin = new BufferedInputStream(fi, BUFFER); 
     ZipEntry entry = new ZipEntry(filePath); 
     zos.putNextEntry(entry); 

     int count; 
     while ((count = origin.read(data, 0, BUFFER)) != -1) 
     { 
      zos.write(data, 0, count); 
     } 
     origin.close(); 

प्राकृतिक समाधान JVM के ढेर स्मृति स्थान विस्तार करने के लिए किया जाएगा, लेकिन मैं अगर वहाँ एक स्ट्रीमिंग तरीके से इस डेटा लिखने के लिए एक विधि है पता करना चाहते हैं। मुझे उच्च संपीड़न दर की आवश्यकता नहीं है इसलिए मैं एल्गोरिदम भी बदल सकता हूं।

क्या किसी को इसके बारे में कोई जानकारी है?

+1

बुफेर कितना बड़ा है? –

+0

जैसा कि मैंने 2048 – robob

उत्तर

8

सैम की प्रतिक्रिया के बारे में आपकी टिप्पणी के अनुसार, आपने स्पष्ट रूप से एक ZipOutputStream बनाया है, जो एक ByteArrayOutputStream को लपेटता है। पाठ्यक्रम के ByteArrayOutputStream स्मृति में संकुचित परिणाम कैश करता है। यदि आप डिस्क पर लिखे गए हैं, तो आपको ZipOutputStream को FileOutputStream के आस-पास लपेटना होगा।

+0

ठीक है मैं समझता हूं कि आपने मुझे क्या बताया लेकिन संकुचित डेटा लगभग 60 एमबीटीई है ... "आउटऑफ स्पेस" ढेर त्रुटि चलाने के लिए बहुत कम है। इसके बारे में क्या है? मुझे अच्छा होने के लिए एक्सएमएक्स 1024 मीटर सेट करना होगा! शायद मेरी गलती है! – robob

+2

+1, डिस्क पर ज़िप लिखने के लिए फ़ाइलऑटपुटस्ट्रीम का उपयोग करें, या यदि आप इसे ब्राउज़र पर सीधे स्ट्रीम करना चाहते हैं तो HttpServletResponse outputStream का उपयोग करें। –

+1

जब 60 एमबीइट्स मेमोरी निकाल दी गई थी तो क्या आप डिफ़ॉल्ट जेवीएम सेटिंग्स का उपयोग कर रहे थे? यदि ऐसा है तो यह सही के बारे में लगता है। भले ही आपका JVM किसी भी समय 64 एम हीप आकार पर चल रहा हो, बाइटएरेऑटपुटस्ट्रीम को उस बाइट [] सरणी का विस्तार करने की आवश्यकता होगी ... जिसका अर्थ है पूर्ण प्रति। – PSpeed

3

TrueZip नामक एक लाइब्रेरी है जिसे मैंने अतीत में इस तरह की चीज करने के लिए अच्छी सफलता के साथ उपयोग किया है।

मैं गारंटी नहीं दे सकता कि यह बफरिंग फ्रंट पर बेहतर होगा। मुझे पता है कि जेडीके के ज़िप एपीआई के मुकाबले यह अपने कोडिंग के साथ बहुत सी चीजें करता है।

तो मेरी राय में, यह एक कोशिश के लायक है।

1

ZipOutputStream स्ट्रीम-आधारित है, यह स्मृति पर नहीं है। आपका बफर बहुत बड़ा हो सकता है।

+0

लिखा था मेरा बफर 2048 बाइट है और मुझे नहीं लगता कि यह बहुत बड़ा है! जावा ढेर अंतरिक्ष \t java.util.Arrays.copyOf पर (Arrays.java:2786) java.io.ByteArrayOutputStream पर \t: धागा "मुख्य" java.lang.OutOfMemoryError में अपवाद: यह अपवाद नहीं है। लिखने (ByteArrayOutputStream.java:94) \t java.util.zip.DeflaterOutputStream.deflate पर (DeflaterOutputStream.java:161) \t java.util.zip.DeflaterOutputStream.write पर (DeflaterOutputStream.java:118) \t जावा में .util.zip.ZipOutputStream.write (ZipOutputStream.java7272) – robob

0

मुझे आश्चर्य है कि ऐसा इसलिए है क्योंकि आप ZipEntry में सामग्री संग्रहीत कर रहे हैं, शायद यह मूल रूप से ZipEntry लिखने से पहले अपनी सभी सामग्री लोड करता है। क्या आपको ज़िप का उपयोग करना है? यदि यह केवल एक डेटा स्ट्रीम है जिसे आपको संपीड़ित करने की आवश्यकता है तो आप इसके बजाय GZIPOutputStream में देख सकते हैं। मेरा मानना ​​है कि इसमें एक ही समस्या नहीं होगी।

उम्मीद है कि इससे मदद मिलती है।

+0

मुझे वेब सेवा – robob

+2

के माध्यम से भेजने के लिए एक ज़िप फ़ाइल में एक निर्देशिका सामग्री को स्टोर करने की आवश्यकता है l यदि आपके जवाब में ऐसी बड़ी वस्तुएं हैं तो एक बुरा विचार है। ज़िप-फ़ाइल को फिर से प्राप्त किया जा सकता है, इसके बजाय एक यूआरएल लौटने पर विचार करें। सादा servlets एक बाइट आधारित स्ट्रीमिंग प्रतिक्रिया के लिए अनुमति देते हैं। –

+0

आप सही हैं मुझे लगता है कि यह सही चयन है। – robob