Я пытаюсь создать простую программу Java, которая читает и извлекает содержание из файла (файлов) в zip-файле. Zip-файл содержит 3 файла (txt, PDF, docx). Я должен считать содержание всех этих файлов, и я использую Apache Tika с этой целью.
Может кто-то помогать мне здесь достигнуть функциональности. Я попробовал это до сих пор, но никакой успех
Фрагмент кода
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 API NIO обеспечивает лучшее и больше универсального способа получить доступ к содержанию файлов Zip или Банки. На самом деле это - теперь объединенный API, который позволяет Вам рассматривать zip-файлы точно как нормальные файлы.
для извлечения всех файлов, содержавших в zip-файле в этом API, Вы сделали бы это:
В 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
, никогда не мог бы повреждаться цикл:
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
Форма, что я могу сказать, принятое решение, не будет работать на случаи, где существуют вложенные 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 передаются как аргументы методам, которые обрабатывают их, и те методы имеют тенденцию сразу закрыть входной поток после того, как они сделаны с ним.