从Zip文件中的文件读取内容
我想创建一个简单的java程序,它从zip文件内的文件中读取和提取内容。 Zip文件包含3个文件(txt,pdf,docx)。我需要阅读所有这些文件的内容,并且为此使用了Apache Tika。从Zip文件中的文件读取内容
有人可以帮助我在这里实现功能。到目前为止,我已经试过,但没有成功
代码段
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,你可以根据需要阅读它。
不要忘记关闭inputStream和ZipFile以避免资源泄漏:)。 – Noremac 2014-07-24 20:51:15
zipFile.entries();有没有为类型zipFile定义的条目函数 – 2014-08-20 02:32:08
有没有办法将byte []数组传递给'ZipFile(content.getBytes())'的构造函数?如果不是,我们该怎么做? – 2014-10-31 12:47:42
由于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
}
感谢您指出while循环中的错误。 – 2013-03-27 19:10:34
您可以使用示例代码让Tika为您处理容器文件。 http://wiki.apache.org/tika/RecursiveMetadata
形式我可以告诉,接受的解决方案将不适用于嵌套zip文件的情况下。不过,Tika也会照顾到这种情况。
我实现这一目标的方法是通过创建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();
这样做的一个优点方法:InputStreams作为参数传递给处理它们的方法,这些方法倾向于在完成输入流后立即关闭输入流。
从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);
}
});
}
}
为什么不直接将zip文件传给Apache Tika?然后它会调用你为zip中每个文件提供的递归解析器,所以你不必做任何特别的事情! – Gagravarr 2013-03-28 04:20:43
这就是我想知道的,但无法获得足够的教程在如何做到这一点。我也对此一点担心 - http://www.javamex.com/tutorials/compression/zip_problems.shtml,不知道如果Tika解决这个问题。 – 2013-03-28 06:42:01
Tika使用commons compress来解决很多这些问题 – Gagravarr 2013-03-28 06:48:17