Elimine archivos de un archivo ZIP sin descomprimir usando Java (preferido) o Python
Hola,
Trabajo con archivos ZIP grandes que contienen muchos cientos de archivos de texto altamente comprimidos. Cuando descomprimo el archivo ZIP, puede tomar un tiempo y consumir fácilmente hasta 20 GB de espacio en disco. Me gustaría eliminar ciertos archivos de estos archivos ZIP sin tener que descomprimir y recomprimir solo los archivos que deseo.
Por supuesto, es ciertamente posible hacerlo a largo plazo, pero muy ineficiente.
Preferiría hacer esto en Java, pero consideraré Python
He encontrado esto en la web
Solución limpia con solo una biblioteca estándar, pero no estoy seguro de si está incluido en el SDK de Android, que se encontrará.
import java.util.*; import java.net.URI; import java.nio.file.Path; import java.nio.file.*; import java.nio.file.StandardCopyOption; public class ZPFSDelete { public static void main(String [] args) throws Exception { /* Define ZIP File System Properies in HashMap */ Map zip_properties = new HashMap<>(); /* We want to read an existing ZIP File, so we set this to False */ zip_properties.put("create", "false"); /* Specify the path to the ZIP File that you want to read as a File System */ URI zip_disk = URI.create("jar:file:/my_zip_file.zip"); /* Create ZIP file System */ try (FileSystem zipfs = FileSystems.newFileSystem(zip_disk, zip_properties)) { /* Get the Path inside ZIP File to delete the ZIP Entry */ Path pathInZipfile = zipfs.getPath("source.sql"); System.out.println("About to delete an entry from ZIP File" + pathInZipfile.toUri() ); /* Execute Delete */ Files.delete(pathInZipfile); System.out.println("File successfully deleted"); } } }
No tengo un código para hacer esto, pero la idea básica es simple y debería traducirse a casi cualquier idioma de la misma manera. El diseño del archivo ZIP es solo una serie de bloques que representan archivos (un encabezado seguido de los datos comprimidos), terminados con un directorio central que solo contiene todos los metadatos. Aquí está el proceso:
Consulte http://en.wikipedia.org/wiki/ZIP_%28file_format%29 para obtener todos los detalles sobre las estructuras de los archivos ZIP.
Como sugiere bestsss, es posible que desee realizar la copia en otro archivo, para evitar la pérdida de datos en caso de falla.
Ok, creo que encontré una solución potencial de http://www.javaer.org. Definitivamente elimina archivos dentro del zip y no creo que esté descomprimiendo nada. Aquí está el código:
public static void deleteZipEntry(File zipFile, String[] files) throws IOException { // get a temp file File tempFile = File.createTempFile(zipFile.getName(), null); // delete it, otherwise you cannot rename your existing zip to it. tempFile.delete(); tempFile.deleteOnExit(); boolean renameOk=zipFile.renameTo(tempFile); if (!renameOk) { throw new RuntimeException("could not rename the file "+zipFile.getAbsolutePath()+" to "+tempFile.getAbsolutePath()); } byte[] buf = new byte[1024]; ZipInputStream zin = new ZipInputStream(new FileInputStream(tempFile)); ZipOutputStream zout = new ZipOutputStream(new FileOutputStream(zipFile)); ZipEntry entry = zin.getNextEntry(); while (entry != null) { String name = entry.getName(); boolean toBeDeleted = false; for (String f : files) { if (f.equals(name)) { toBeDeleted = true; break; } } if (!toBeDeleted) { // Add ZIP entry to output stream. zout.putNextEntry(new ZipEntry(name)); // Transfer bytes from the ZIP file to the output file int len; while ((len = zin.read(buf)) > 0) { zout.write(buf, 0, len); } } entry = zin.getNextEntry(); } // Close the streams zin.close(); // Compress the files // Complete the ZIP file zout.close(); tempFile.delete();
}
Sí, es posible que JAVA utilice una biblioteca llamada TRUEZIP .
TrueZIP es un sistema de archivos virtuales (VFS) basado en Java que permite que las aplicaciones cliente realicen operaciones CRUD (Crear, Leer, Actualizar, Eliminar) en archivos comprimidos como si fueran directorios virtuales, incluso con archivos archivados nesteds en entornos multiproceso.
Consulte el siguiente enlace para obtener más información https://truezip.java.net/
Esto puede ser viejo, pero aquí hay una manera. Y funciona porque lo uso constantemente y funciona bien.
public boolean deleteFile(String zip_dir, String subfile){ delete(new File(zipdir, subfile)); } private void delete(File file) { if(file == null || !file.exists()) return; if(file.isFile()) { file.delete(); return; } File children[] = file.listFiles(); for(int i = 0; i < children.length; i++) { File child = children[i]; if(child.isFile()) child.delete(); else delete(child); } file.delete(); }