在Java或Python中,无需解压缩即可从ZIP档案中删除文件

9 投票
4 回答
24309 浏览
提问于 2025-04-16 13:20

用Java(优先)或Python从ZIP压缩包中删除文件,而不需要解压缩

你好,

我在处理一些很大的ZIP文件,这些文件里有几百个压缩得很厉害的文本文件。当我解压这个ZIP文件时,可能会花费一些时间,而且会占用多达20GB的磁盘空间。我想从这些ZIP文件中删除某些文件,但不想解压缩整个文件,然后再把我想要的文件重新压缩。

当然,长时间的操作是可以做到的,但效率太低了。

我更倾向于用Java来做这个,但也会考虑用Python。

4 个回答

1

是的,使用一个叫TRUEZIP的库,JAVA是可以做到的。

TrueZIP是一个基于Java的虚拟文件系统(VFS),它让客户端应用程序可以像操作虚拟文件夹一样,对压缩文件进行增删改查(创建、读取、更新、删除)操作,甚至可以处理里面嵌套的压缩文件,并且支持多线程环境。

想了解更多信息,可以查看下面的链接: https://christian-schlichtherle.bitbucket.io/truezip/

2

我没有具体的代码来实现这个,但基本思路很简单,几乎可以用任何编程语言来实现。ZIP文件的结构就是一系列的块,每个块代表一个文件(先是文件头,然后是压缩数据),最后是一个中央目录,里面存放所有的元数据。下面是具体的步骤:

  1. 在文件中向前扫描,直到找到你想删除的第一个文件。
  2. 继续向前扫描,直到找到你想删除的第一个文件或者到达中央目录。
  3. 再向前扫描,直到找到你想删除的第一个文件或者到达中央目录。
  4. 把第三步找到的所有数据复制到第二步跳过的地方,直到找到另一个想删除的文件或者到达中央目录。
  5. 如果没有到达中央目录,就回到第二步。
  6. 把中央目录复制到你停止复制的地方,省略掉被删除文件的条目,并调整偏移量,以反映你移动了每个文件的量。

想了解ZIP文件结构的详细信息,可以查看这个链接

正如bestsss所建议的,你可能想把复制的内容放到另一个文件中,这样可以防止在出现故障时丢失数据。

6

我在网上找到这个链接,里面有一个很好的解决方案,感谢Java 7。

这个方法很简单,只用了标准库,但我不确定它是否包含在Android SDK里,可能需要查一下。

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<String, String> 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");   
        } 
    }
}

撰写回答