java - leer - Lea el contenido de los archivos que están dentro del archivo Zip
comprimir una carpeta en zip java (5)
A partir de Java 7, NIO Api proporciona una forma mejor y más genérica de acceder a los contenidos de los archivos Zip o Jar. En realidad, ahora es una API unificada que le permite tratar archivos Zip exactamente como los archivos normales.
Para extraer todos los archivos contenidos dentro de un archivo comprimido en esta API, harías esto:
En 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));
});
}
En 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);
}
});
}
}
Intento crear un programa Java simple que lea y extraiga el contenido del archivo (s) dentro del archivo zip. El archivo zip contiene 3 archivos (txt, pdf, docx). Necesito leer el contenido de todos estos archivos y estoy usando Apache Tika para este propósito.
¿Alguien puede ayudarme aquí para lograr la funcionalidad? Lo he intentado hasta ahora pero no he tenido éxito
Fragmento de código
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();
}
}
}
Código de muestra que puede usar para dejar que Tika se encargue de los archivos contenedores para usted. http://wiki.apache.org/tika/RecursiveMetadata
Forma lo que puedo decir, la solución aceptada no funcionará para los casos en que haya archivos zip anidados. Tika, sin embargo, se encargará de tales situaciones también.
Debido a la condición en while
, el bucle puede que nunca se rompa:
while (entry != null) {
// If entry never becomes null here, loop will never break.
}
En lugar de la verificación null
, puede intentar esto:
ZipEntry entry = null;
while ((entry = zip.getNextEntry()) != null) {
// Rest of your code
}
Mi manera de lograr esto es creando la clase de envoltura ZipInputStream que manejaría eso que proporcionaría solo la corriente de la entrada actual:
La clase de envoltura:
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();
}
}
El uso de esto:
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();
Una de las ventajas de este enfoque: InputStreams se pasan como argumentos a los métodos que los procesan y esos métodos tienden a cerrar inmediatamente el flujo de entrada una vez que terminan.
Si se pregunta cómo obtener el contenido del archivo de cada ZipEntry
, en realidad es bastante simple. Aquí hay un código de muestra:
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);
}
}
Una vez que tenga InputStream, puede leerlo como lo desee.