2013-03-27 9 views
38

के अंदर फ़ाइलों से सामग्री पढ़ें, मैं एक साधारण जावा प्रोग्राम बनाने की कोशिश कर रहा हूं जो ज़िप फ़ाइल के अंदर फ़ाइल (फाइलों) से सामग्री को पढ़ता है और निकालता है। ज़िप फ़ाइल में 3 फाइलें हैं (txt, pdf, docx)। मुझे इन सभी फ़ाइलों की सामग्री को पढ़ने की जरूरत है और मैं इस उद्देश्य के लिए अपाचे टिका का उपयोग कर रहा हूं।ज़िप फ़ाइल

कोई भी कार्यक्षमता प्राप्त करने के लिए यहां मेरी सहायता कर सकता है। मैं अब तक इस की कोशिश की है, लेकिन कोई सफलता

कोड स्निपेट

public class SampleZipExtract { 


    public static void main(String[] args) { 

     List<String> tempString = new ArrayList<String>(); 
     StringBuffer sbf = new StringBuffer(); 

     File file = new File("C:\\Users\\xxx\\Desktop\\abc.zip"); 
     InputStream input; 
     try { 

      input = new FileInputStream(file); 
      ZipInputStream zip = new ZipInputStream(input); 
      ZipEntry entry = zip.getNextEntry(); 

      BodyContentHandler textHandler = new BodyContentHandler(); 
      Metadata metadata = new Metadata(); 

      Parser parser = new AutoDetectParser(); 

      while (entry!= null){ 

       if(entry.getName().endsWith(".txt") || 
          entry.getName().endsWith(".pdf")|| 
          entry.getName().endsWith(".docx")){ 
       System.out.println("entry=" + entry.getName() + " " + entry.getSize()); 
        parser.parse(input, textHandler, metadata, new ParseContext()); 
        tempString.add(textHandler.toString()); 
       } 
      } 
      zip.close(); 
      input.close(); 

      for (String text : tempString) { 
      System.out.println("Apache Tika - Converted input string : " + text); 
      sbf.append(text); 
      System.out.println("Final text from all the three files " + sbf.toString()); 
     } catch (FileNotFoundException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (SAXException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (TikaException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
    } 
} 
+1

ज़िप फ़ाइल को सीधे अपाचे टिका को क्यों पास न करें? इसके बाद आप ज़िप में प्रत्येक फ़ाइल के लिए रिकर्सिंग पार्सर को कॉल करेंगे, इसलिए आपको कुछ भी विशेष करने की ज़रूरत नहीं है! – Gagravarr

+0

यही वह था जो मैं सोच रहा था लेकिन ऐसा करने के तरीके में पर्याप्त ट्यूटोरियल नहीं मिला। मैं इसके बारे में भी चिंतित हूं - http://www.javamex.com/tutorials/compression/zip_problems.shtml, यह सुनिश्चित नहीं है कि Tika इस समस्या को संबोधित करता है या नहीं। –

+0

Tika उन मुद्दों में से कई को पाने के लिए कॉमन्स संपीड़न का उपयोग करता है – Gagravarr

उत्तर

107

यदि आप सोच रहे हैं कि प्रत्येक ZipEntry से फ़ाइल सामग्री कैसे प्राप्त करें, यह वास्तव में काफी सरल है। यहां एक नमूना कोड है:

public static void main(String[] args) throws IOException { 
    ZipFile zipFile = new ZipFile("C:/test.zip"); 

    Enumeration<? extends ZipEntry> entries = zipFile.entries(); 

    while(entries.hasMoreElements()){ 
     ZipEntry entry = entries.nextElement(); 
     InputStream stream = zipFile.getInputStream(entry); 
    } 
} 

एक बार जब आपके पास इनपुटस्ट्रीम हो तो आप इसे पढ़ सकते हैं।

+10

संसाधन रिसाव से बचने के लिए इनपुटस्ट्रीम और ज़िपफाइल को बंद करना न भूलें :)। – Noremac

+2

zipFile.entries(); टाइप ZipFile –

+1

के लिए परिभाषित कोई प्रविष्टि फ़ंक्शन नहीं है, क्या 'ZipFile (content.getBytes()) के निर्माता को बाइट [] सरणी पास करने का कोई तरीका है? अगर नहीं तो हम यह कैसे कर सकते हैं? –

9
while में हालत की वजह से

, पाश तोड़ कभी नहीं हो सकता है:

while (entry != null) { 
    // If entry never becomes null here, loop will never break. 
} 
null जांच करने के बजाय

वहाँ , आप इसे आजमा सकते हैं:

ZipEntry entry = null; 
while ((entry = zip.getNextEntry()) != null) { 
    // Rest of your code 
} 
+0

लूप के दौरान गलती को इंगित करने के लिए धन्यवाद। –

3

नमूना कोड जिसका उपयोग आप टिका को आपके लिए कंटेनर फाइलों का ख्याल रखने के लिए कर सकते हैं। http://wiki.apache.org/tika/RecursiveMetadata

फॉर्म जो मैं बता सकता हूं, स्वीकार्य समाधान उन मामलों के लिए काम नहीं करेगा जहां नेस्टेड ज़िप फ़ाइलें हैं। हालांकि, टीका भी ऐसी परिस्थितियों का ख्याल रखेगी।

1

इस को प्राप्त करने का मेरा तरीका ZipInputStream रैपिंग वर्ग बनाने के द्वारा यह है कि संभाल होता है कि केवल वर्तमान प्रविष्टि की धारा प्रदान करेगा:

आवरण वर्ग:

public class ZippedFileInputStream extends InputStream { 

    private ZipInputStream is; 

    public ZippedFileInputStream(ZipInputStream is){ 
     this.is = is; 
    } 

    @Override 
    public int read() throws IOException { 
     return is.read(); 
    } 

    @Override 
    public void close() throws IOException { 
     is.closeEntry(); 
    } 

}

उपयोग इसका:

ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream("SomeFile.zip")); 

    while((entry = zipInputStream.getNextEntry())!= null) { 

    ZippedFileInputStream archivedFileInputStream = new ZippedFileInputStream(zipInputStream); 

    //... perform whatever logic you want here with ZippedFileInputStream 

    // note that this will only close the current entry stream and not the ZipInputStream 
    archivedFileInputStream.close(); 

    } 
    zipInputStream.close(); 

इसका एक फायदा दृष्टिकोण: इनपुटस्ट्रीम को उन तरीकों के लिए एक तर्क के रूप में पारित किया जाता है जो उन्हें संसाधित करते हैं और उन तरीकों के साथ इनपुट स्ट्रीम को तत्काल बंद करने की प्रवृत्ति होती है।

25

जावा 7 के रूप में, एनआईओ एपी ज़िप या जार फ़ाइलों की सामग्री तक पहुंचने का एक बेहतर और अधिक सामान्य तरीका प्रदान करता है। असल में, यह अब एक एकीकृत एपीआई है जो आपको सामान्य फ़ाइलों की तरह ज़िप फ़ाइलों का इलाज करने की अनुमति देता है।जावा 8 में

: जावा 7 में

private void extractAll(URI fromZip, Path toDirectory) throws IOException{ 
    FileSystems.newFileSystem(fromZip, Collections.emptyMap()) 
      .getRootDirectories() 
      .forEach(root -> { 
       // in a full implementation, you'd have to 
       // handle directories 
       Files.walk(root).forEach(path -> Files.copy(path, toDirectory)); 
      }); 
} 

आदेश में इस एपीआई में एक ज़िप फ़ाइल के अंदर निहित फ़ाइलों के सभी निकालने के लिए, यदि आप ऐसा करते हैं:

private void extractAll(URI fromZip, Path toDirectory) throws IOException{ 
    FileSystem zipFs = FileSystems.newFileSystem(fromZip, Collections.emptyMap()); 

    for(Path root : zipFs.getRootDirectories()) { 
     Files.walkFileTree(root, new SimpleFileVisitor<Path>() { 
      @Override 
      public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) 
        throws IOException { 
       // You can do anything you want with the path here 
       Files.copy(file, toDirectory); 
       return FileVisitResult.CONTINUE; 
      } 

      @Override 
      public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) 
        throws IOException { 
       // In a full implementation, you'd need to create each 
       // sub-directory of the destination directory before 
       // copying files into it 
       return super.preVisitDirectory(dir, attrs); 
      } 
     }); 
    } 
} 
+2

पर देना यह दोनों भयानक और पागल है। ऑपरेशन के बाद – Esko

+0

'फाइलसिस्टम' बंद होना चाहिए। –

+0

जावा 8 संस्करण में, 'Files.walk (रूट)' IOException फेंकता है जो लैम्ब्डा के माध्यम से प्रचार नहीं कर सकता है। – Barteks2x

संबंधित मुद्दे