2010-09-14 25 views
6

के भीतर एक ज़िप फ़ाइल पढ़ना पहले हमारे पास हमारे वेब एप्लिकेशन में कुछ ज़िप फ़ाइलें थीं। हम ज़िप फ़ाइल के भीतर एक विशिष्ट पाठ दस्तावेज़ को पर्स करना चाहते हैं। यह कोई समस्या नहीं थी:एक जार फ़ाइल

URL url = getClass().getResource(zipfile); 
ZipFile zip = new ZipFile(url.getFile().replaceAll("%20", " "));  
Entry entry = zip.getEntry("file.txt"); 

InputStream is = zip.getInputStream(entry); 
BufferedReader reader = new BufferedReader(new InputStreamReader(is)); 

String line = reader.readLine(); 
while (line != null) { 
    // do stuff 
} 

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

InputStream is = getClass().getResourceAsStream(zipfile); 
ZipInputStream zis = new ZipInputStream(is); 

ZipEntry entry = zis.getNextEntry(); 
while (entry != null && !entry.getName().equals("file.txt")) { 
    entry = zis.getNextEntry(); 
} 

लेकिन मेरे पास प्रविष्टि के लिए इनपुट स्ट्रीम प्राप्त करने का कोई तरीका नहीं है। मैंने प्रविष्टि की लंबाई खोजने और ZipInputStream से अगले एन बाइट्स प्राप्त करने का प्रयास किया लेकिन यह मेरे लिए काम नहीं करता था। ऐसा लगता है कि सभी बाइट पढ़े गए थे 0.

क्या इस दौर में कोई रास्ता है या क्या मुझे ज़िप फ़ाइलों को मूल परियोजना में वापस ले जाना होगा?

उत्तर

4

एंट्री आपको आंतरिक-ज़िप फ़ाइल का इनपुटस्ट्रीम दे सकता है।

InputStream innerzipstream = zip.getInputStream(entry); 

तो तुम

new ZipInputStream(innerzipstream); 

का उपयोग करें और (भीतरी ज़िप फ़ाइल की सामग्री एक आदेश दिया फैशन में पुनः प्राप्त करने के ZipInputStream पूछ सकते हैं, तो आप रैंडम एक्सेस, क्योंकि यह एक ZipInputStream है की जरूरत नहीं है)

http://download.oracle.com/javase/1.4.2/docs/api/java/util/zip/ZipInputStream.html

अनुक्रमिक ज़िप पहुँच पर देखो

ZipInputStream के रूप में धारा एक इनपुट से एक ज़िप फ़ाइल पढ़ रहा है यह क्रम में काम करने के लिए दिया गया है:

// DO THIS for each entry 
ZipEntry e = zipInputStreamObj.getNextEntry(); 
e.getName // and all data 
int size = e.getSize(); // the byte count 
while (size > 0) { 
    size -= zipInputStreamObj.read(...); 
} 
zipInputStreamObj.closeEntry(); 
// DO THIS END 

zipInputStreamObj.close(); 

नोट: मैं नहीं जानता कि यदि ZipInputStream.getNextEntry() अशक्त लौटाता है जब जिप के अंत फ़ाइल पहुंची है या नहीं। मुझे उम्मीद है क्योंकि मुझे कोई और प्रविष्टि नहीं होने पर एहसास करने का दूसरा तरीका नहीं पता है।

+0

वास्तव में, आप बाहरी पढ़ने के लिए Class.getResourceAsStream और ZipInputStream उपयोग कर सकते हैं -जिप भी। इस तरह, आपको विज्ञापन-प्रसार फ़ाइल नाम बदलने की आवश्यकता नहीं है और फ़ाइल पहुंच के लिए URL पर भरोसा नहीं है। – helios

6

TrueZip के बारे में कैसे? इसका उपयोग करके आप ज़िप्ड फ़ाइल को बस खोल सकते हैं जैसे कि यह निर्देशिका के अंदर स्थित था।

new FileOutputStream("/path/to/some-jar.jar/internal/zip/file.zip/myfile.txt"); 

दस्तावेज़ों के अनुसार, अनंत घोंसले भी समर्थित है। मैंने अभी तक इस परियोजना का उपयोग नहीं किया है, लेकिन यह थोड़ी देर के लिए मेरे रडार पर रहा है और यह आपकी समस्या पर लागू होता है।

परियोजना स्थल: http://truezip.java.net/ (संपादित)

0

मैं ऊपर प्रदान की अनुक्रमिक पिन पहुँच को संशोधित किया है:

File destFile = new File(destDir, jarName); 
JarOutputStream jos = new JarOutputStream(new FileOutputStream(destFile)); 

JarInputStream jis = new JarInputStream(is); 
JarEntry jarEntry = jis.getNextJarEntry(); 
for (; jarEntry != null ; jarEntry = jis.getNextJarEntry()) { 
    jos.putNextEntry(new JarEntry(jarEntry.getName())); 
    if(jarEntry.isDirectory()) { 
     continue; 
    } 

    int bytesRead = jis.read(buffer); 
    while(bytesRead != -1) { 
    jos.write(buffer, 0, bytesRead); 
    bytesRead = jis.read(buffer); 
    } 

} 
is.close(); 
jis.close(); 
jos.flush(); 
jos.closeEntry(); 
jos.close(); 

उपरोक्त कोड में, मैं एक जार फ़ाइल के अंदर एक जार फ़ाइल की प्रतिलिपि कोशिश कर रहा हूँ फाइल सिस्टम में एक फ़ोल्डर के लिए। 'है' एक अन्य जार फ़ाइल (jar.getInputStream ("lib/abcd.jar") के अंदर जार फ़ाइल में इनपुट स्ट्रीम है)

0

स्ट्रिंग को पार्स करना और ZipInputStream को किसी अन्य ZipInputStream पर खोलना भी संभव है और फ़ाइल को अंदर फ़ाइल में सेट करें।

उदा। आप ऊपर की तरह स्ट्रिंग है "path/to/कुछ-jar.jar/आंतरिक/ज़िप/file.zip/myfile.txt"

private static final String[] zipFiles = new String[] { ".zip", ".jar" }; 

public static InputStream getResourceAsStream(final String ref) throws IOException { 
    String abstractPath = ref.replace("\\", "/"); 
    if (abstractPath.startsWith("/")) { 
     abstractPath = abstractPath.substring(1); 
    } 
    final String[] pathElements = abstractPath.split("/"); 
    return getResourceAsStream(null, pathElements); 
} 

private static InputStream getResourceAsStream(final ZipInputStream parentStream, final String[] pathElements) 
     throws IOException { 

    if (pathElements.length == 0) return parentStream; 

    final StringBuilder nextFile = new StringBuilder(); 
    for (int index = 0; index < pathElements.length; index++) { 
     final String pathElement = pathElements[index]; 
     nextFile.append((index > 0 ? "/" : "") + pathElement); 
     if (pathElement.contains(".")) { 
      final String path = nextFile.toString(); 
      if (checkForZip(pathElement)) { 
       final String[] restPath = new String[pathElements.length - index - 1]; 
       System.arraycopy(pathElements, index + 1, restPath, 0, restPath.length); 
       if (parentStream != null) { 
        setZipToEntry(parentStream, path); 
        return getResourceAsStream(new ZipInputStream(parentStream), restPath); 
       } else return getResourceAsStream(new ZipInputStream(new FileInputStream(path)), restPath); 
      } else { 
       if (parentStream != null) { 
        setZipToEntry(parentStream, path); 
        return parentStream; 
       } else return new FileInputStream(path); 
      } 
     } 
    } 
    throw new FileNotFoundException("File not found: " + nextFile.toString()); 
} 

private static void setZipToEntry(final ZipInputStream in, final String name) throws IOException { 
    ZipEntry entry; 
    while ((entry = in.getNextEntry()) != null) { 
     if (entry.getName().equals(name)) return; 
    } 
    throw new FileNotFoundException("File not found: " + name); 
} 

private static boolean checkForZip(final String ref) { 
    for (final String zipFile : zipFiles) { 
     if (ref.endsWith(zipFile)) return true; 
    } 
    return false; 
} 
संबंधित मुद्दे