2008-09-15 12 views
16

मैं एक java.util.zip.ZipInputStream से एक एकल फाइल को पढ़ने के लिए कोशिश कर रहा हूँ, और एक java.io.ByteArrayOutputStream में कॉपी (ताकि मैं तो एक java.io.ByteArrayInputStream बना सकते हैं और हाथ है कि एक 3 पार्टी पुस्तकालय है कि बंद करने खत्म हो जाएगा करने के लिए कर सकते हैं में एक ZipInputStream से पढ़ना स्ट्रीम, और मैं नहीं चाहता कि मेरा ZipInputStream बंद हो रहा हो)।एक ByteArrayOutputStream

मैं शायद यहाँ कुछ बुनियादी याद कर रहा हूँ, लेकिन मैं कभी नहीं, जबकि पाश यहां दर्ज करें:

ByteArrayOutputStream streamBuilder = new ByteArrayOutputStream(); 
int bytesRead; 
byte[] tempBuffer = new byte[8192*2]; 
try { 
    while ((bytesRead = zipStream.read(tempBuffer)) != -1) { 
     streamBuilder.write(tempBuffer, 0, bytesRead); 
    } 
} catch (IOException e) { 
    // ... 
} 

मैं क्या याद आ रही है कि मुझे धारा कॉपी कर सकते हैं?

संपादित करें:

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

इसके अलावा, कोड के इस स्निपेट को प्राप्त करने से पहले ZipInputStream पर मैंने पहले ही getNextEntry() कहा है। अगर मैं फ़ाइल को किसी अन्य InputStream (ऊपर उल्लिखित OutputStream के माध्यम से) में कॉपी करने की कोशिश नहीं करता हूं, और बस मेरी तीसरी पार्टी लाइब्रेरी में ZipInputStream पास करें, लाइब्रेरी स्ट्रीम बंद कर देती है, और मैं कुछ और नहीं कर सकता, जैसे कि धारा में शेष फाइलें।

+1

तुम अब परवाह नहीं है, लेकिन ** आप सभी डेटा की प्रतिलिपि से बच सकते हैं ** और धारा को बंद 3 डी पक्ष लाइब्रेरी से बचने यदि आप मूल इनपुट स्ट्रीम (zipStream) लपेट और करीब विधि ओवरराइड । 1) सार्वजनिक कक्षा बनाएं DontCloseInputStream FilterInputStream को बढ़ाता है। 2) एक कन्स्ट्रक्टर (इनपुटस्ट्रीम इन) बनाएं जो सुपर (इन) 3 कहता है) बंद विधि को ओवरराइड करें और कुछ भी नहीं करें 4) नया डोंटक्लोस इनपुटस्ट्रीम (ज़िपस्ट्रीम) बनाएं 5) इसे लाइब्रेरी में पास करें। और * voi lá * – helios

+0

और आउटपुटस्ट्रीम पर एक इनपुटस्ट्रीम की प्रतिलिपि बनाने के लिए कॉमन्स-फ़ाइल अपलोड लोड लाइब्रेरी (अपाचे) में स्ट्रीम नामक एक उपयोगिता वर्ग है। आप Streams.copy (इन, आउट, क्लोज़?) करते हैं और यह हो गया है। – helios

+0

तो zipEntry.getSize() वापस क्या करता है? इस मामले में –

उत्तर

7

आपका लूप मान्य दिखता है - निम्न कोड (केवल अपने ही) पर वापस लौटाता है?

zipStream.read(tempBuffer) 

यदि यह लौटा रहा है -1, तो ज़िप प्राप्त करने से पहले ज़िपस्ट्रीम बंद हो जाता है, और सभी दांव बंद हो जाते हैं। अब आपके डीबगर का उपयोग करने और यह सुनिश्चित करने का समय है कि आपके पास क्या हो रहा है वास्तव में मान्य है।

जब आप getNextEntry() को कॉल करते हैं, तो क्या यह एक मान देता है, और प्रविष्टि में डेटा अर्थपूर्ण है (यानी कॉम्प्रेस्ड साइज() वैध मान देता है)? अगर आप सिर्फ एक ज़िप फ़ाइल पढ़ रहे हैं जिसमें एम्बेडेड रीड-अग्रेषित ज़िप प्रविष्टियां नहीं हैं, तो ZipInputStream आपके लिए काम नहीं करेगा।

ज़िप प्रारूप के बारे में कुछ उपयोगी छोटी-मोटी बातें:

प्रत्येक फ़ाइल एक ज़िप फ़ाइल में एम्बेडेड एक हैडर है। इस हेडर में उपयोगी जानकारी हो सकती है (जैसे स्ट्रीम की संपीड़ित लंबाई, यह फ़ाइल में ऑफसेट है, सीआरसी) - या इसमें कुछ जादू मान हो सकते हैं जो मूल रूप से कहते हैं 'जानकारी स्ट्रीम हेडर में नहीं है, आपको जांचना होगा ज़िप पोस्ट-एम्बल '।

प्रत्येक ज़िप फ़ाइल में तब एक तालिका होती है जो फ़ाइल के अंत से जुड़ी होती है जिसमें वास्तविक डेटा के साथ सभी ज़िप प्रविष्टियां होती हैं। अंत में तालिका अनिवार्य है, और इसमें मान सही होना चाहिए। इसके विपरीत, स्ट्रीम में एम्बेडेड मान प्रदान नहीं किए जाने चाहिए।

यदि आप ज़िपफाइल का उपयोग करते हैं, तो यह ज़िप के अंत में तालिका को पढ़ता है। यदि आप ZipInputStream का उपयोग करते हैं, तो मुझे संदेह है कि getNextEntry() स्ट्रीम में एम्बेडेड प्रविष्टियों का उपयोग करने का प्रयास करता है। यदि वे मान निर्दिष्ट नहीं हैं, तो ZipInputStream को पता नहीं है कि स्ट्रीम कितनी देर हो सकती है। फुलाए एल्गोरिदम स्वयं को समाप्त कर रहा है (आउटपुट को पूरी तरह से पुनर्प्राप्त करने के लिए आपको वास्तव में आउटपुट स्ट्रीम की असम्पीडित लंबाई जानने की आवश्यकता नहीं है), लेकिन यह संभव है कि इस पाठक का जावा संस्करण इस स्थिति को बहुत अच्छी तरह से संभाल नहीं सके।

मैं कहना है कि यह एक ZipInputStream लौटने एक सर्वलेट के लिए काफी असामान्य है (यह एक inflatorInputStream अगर आप संकुचित सामग्री प्राप्त होने जा रहे हैं प्राप्त करने के लिए और अधिक आम है।

+0

जावा में ज़िप इनपुटपुट इस अच्छी तरह से संभाल नहीं लेता है। इसे पोस्ट करने के लिए धन्यवाद। –

-1

जांचें कि भिक्षा में इनपुट स्ट्रीम स्थित है या नहीं।

अन्यथा, कार्यान्वयन के रूप में: मुझे नहीं लगता कि आपको पढ़ने के दौरान परिणाम स्ट्रीम पर लिखने की आवश्यकता है, जब तक कि आप इस सटीक स्ट्रीम को किसी अन्य थ्रेड में संसाधित न करें।

बस एक बाइट सरणी बनाएं, इनपुट स्ट्रीम पढ़ें, फिर आउटपुट स्ट्रीम बनाएं।

0

यह स्पष्ट नहीं है कि आपको ज़िपस्ट्रीम कैसे मिला। यह काम करना चाहिए जब आप इसे इस तरह से मिलता है:

zipStream = zipFile.getInputStream(zipEntry) 
+0

मैंने अभी इसके बारे में एक स्पष्टीकरण जोड़ा है, लेकिन यह फ़ाइल से कम नहीं है। – pkaeding

4

मैं परियोजना कब कॉमन्स से IOUtils का उपयोग करेंगे।

IOUtils.copy(zipStream, byteArrayOutputStream); 
+0

ऐसा लगता है कि यह काम कर सकता है। कल जब मैं काम करता हूं तो मैं कोशिश करूंगा। धन्यवाद। – pkaeding

6

आप शायद एक FileInputStream इस तरह से पढ़ने की कोशिश की:

ZipInputStream in = new ZipInputStream(new FileInputStream(...));

यह नहीं होगा काम के बाद से एक ज़िप संग्रह से अधिक फ़ाइलों को शामिल कर सकते हैं और आप जो फ़ाइल को पढ़ने के लिए निर्दिष्ट करने के लिए की जरूरत है।

आप java.util.zip.ZipFile और IOUtils from Apache Commons IO या ByteStreams from Guava जैसी लाइब्रेरी का उपयोग कर सकते हैं जो स्ट्रीम की प्रतिलिपि बनाने में आपकी सहायता करता है।

उदाहरण: कैसे आप zipStream मिला

ByteArrayOutputStream out = new ByteArrayOutputStream(); 
try (ZipFile zipFile = new ZipFile("foo.zip")) { 
    ZipEntry zipEntry = zipFile.getEntry("fileInTheZip.txt"); 

    try (InputStream in = zipFile.getInputStream(zipEntry)) { 
     IOUtils.copy(in, out); 
    } 
} 
+0

यह क्यों काम नहीं करेगा? धन्यवाद – Edmondo1984

+0

मैंने अपना जवाब अपडेट कर लिया है और एक स्पष्टीकरण जोड़ा है। –

0

टी स्पष्ट नहीं है।

zipStream = zipFile.getInputStream(zipEntry) 

आप एक zipfile से ZipInputStream प्राप्त कर रहे हैं, तो आप 3 डी पार्टी पुस्तकालय के लिए एक धारा प्राप्त कर सकते हैं, यह इसका इस्तेमाल करते हैं, और आप का उपयोग कर किसी अन्य इनपुट स्ट्रीम प्राप्त: जब आप इसे इस तरह से मिलता है यह काम करना चाहिए पहले कोड

याद रखें, इनपुटस्ट्रीम एक कर्सर है। यदि आपके पास पूरा डेटा है (जैसे ज़िपपाइल) तो आप इसके ऊपर एन कर्सर मांग सकते हैं।

एक अलग मामला यह है कि यदि आपके पास केवल "GZip" इनपुटस्ट्रीम है, केवल एक ज़िप्ड बाइट स्ट्रीम है। उस स्थिति में आप ByteArrayOutputStream बफर सभी समझ में आता है।

1

मैं ZipInputStream पर getNextEntry() को कॉल करता हूं जब तक कि यह आपके इच्छित प्रविष्टि पर नहीं है (ZipEntry.getName() इत्यादि का उपयोग करें)। कॉलिंग getNextEntry() कॉल करने से प्रविष्टि की शुरुआत में "कर्सर" अग्रिम करेगा। फिर, zipInputry.getSize() का उपयोग यह निर्धारित करने के लिए करें कि zipInputStream.read() का उपयोग करके आपको कितने बाइट्स को पढ़ना चाहिए।

+0

मैंने वास्तव में इस स्निपेट पर जाने से पहले getNextEntry() कहा है। मैंने अभी सवाल के लिए कुछ स्पष्टीकरण जोड़ा है। – pkaeding

3

आप ज़िपपूटस्ट्रीम के चारों ओर अपने स्वयं के रैपर को कार्यान्वित कर सकते हैं जो निकट() को अनदेखा करता है और तीसरे पक्ष की लाइब्रेरी में हाथ रखता है।

thirdPartyLib.handleZipData(new CloseIgnoringInputStream(zipStream)); 


class CloseIgnoringInputStream extends InputStream 
{ 
    private ZipInputStream stream; 

    public CloseIgnoringInputStream(ZipInputStream inStream) 
    { 
     stream = inStream; 
    } 

    public int read() throws IOException { 
     return stream.read(); 
    } 

    public void close() 
    { 
     //ignore 
    } 

    public void reallyClose() throws IOException 
    { 
     stream.close(); 
    } 
} 
+0

यह एक दिलचस्प विचार है .... अगर कुछ और काम नहीं करता है, तो शायद मैं इसे आजमाउंगा। – pkaeding

0

private static byte[] getZipArchiveContent(File zipName) throws WorkflowServiceBusinessException { 

    BufferedInputStream buffer = null; 
    FileInputStream fileStream = null; 
    ByteArrayOutputStream byteOut = null; 
    byte data[] = new byte[BUFFER]; 

    try { 
    try { 
    fileStream = new FileInputStream(zipName); 
    buffer = new BufferedInputStream(fileStream); 
    byteOut = new ByteArrayOutputStream(); 

    int count; 
    while((count = buffer.read(data, 0, BUFFER)) != -1) { 
    byteOut.write(data, 0, count); 
    } 
    } catch(Exception e) { 
    throw new WorkflowServiceBusinessException(e.getMessage(), e); 
    } finally { 
    if(null != fileStream) { 
    fileStream.close(); 
    } 
    if(null != buffer) { 
    buffer.close(); 
    } 
    if(null != byteOut) { 
    byteOut.close(); 
    } 
    } 
    } catch(Exception e) { 
    throw new WorkflowServiceBusinessException(e.getMessage(), e); 
    } 
    return byteOut.toByteArray(); 

} 
bellow कोड का प्रयास करें

पदों के लिए;

2

आप कॉल

ZipEntry प्रविष्टि = (ZipEntry) zipStream.getNextEntry (भूल रहे हैं) पहली प्रविष्टि के पहले बाइट डिकंप्रेस्ड।

ByteArrayOutputStream streamBuilder = new ByteArrayOutputStream(); 
int bytesRead; 
byte[] tempBuffer = new byte[8192*2]; 
ZipEntry entry = (ZipEntry) zipStream.getNextEntry(); 
try { 
    while ((bytesRead = zipStream.read(tempBuffer)) != -1){ 
     streamBuilder.write(tempBuffer, 0, bytesRead); 
    } 
} catch (IOException e) { 
     ... 
} 
शायद
संबंधित मुद्दे