从Zip文件中的文件读取内容

我正在尝试创build一个简单的java程序,它从zip文件内的文件中读取和提取内容。 Zip文件包含3个文件(txt,pdf,docx)。 我需要阅读所有这些文件的内容,我正在使用Apache Tika来达到这个目的。

有人可以帮助我在这里实现function。 我迄今尝试过,但没有成功

代码片段

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(); } } } 

如果你想知道如何从每个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); } } 

一旦你有InputStream你可以阅读它,但是你想要的。

从Java 7开始,NIO Api提供了一种更好,更通用的方式来访问Zip或Jar文件的内容。 实际上,它现在是一个统一的API,它允许你像普通文件一样对待Zip文件。

为了提取这个API中一个zip文件中包含的所有文件,你需要这样做:

在Java 8中:

 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)); }); } 

在java 7中:

 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); } }); } } 

由于时间的条件,循环可能永远不会中断:

 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 } 

您可以使用示例代码让Tika为您处理容器文件。 http://wiki.apache.org/tika/RecursiveMetadata

forms我可以告诉,接受的解决scheme将不适用于有嵌套的zip文件的情况下。 但是Tika也会照顾到这种情况。

我的方式是通过创buildZipInputStream包装类来处理,只提供当前条目的stream:

包装类:

 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(); 

这种方法的一个优点是:InputStreams作为parameter passing给处理它们的方法,这些方法有一种趋势,就是在inputstream完成之后立即closuresinputstream。