Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/286.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从ZIP存档中删除文件,而无需使用Java或Python进行解压缩_Java_Python_Zip - Fatal编程技术网

从ZIP存档中删除文件,而无需使用Java或Python进行解压缩

从ZIP存档中删除文件,而无需使用Java或Python进行解压缩,java,python,zip,Java,Python,Zip,无需使用Java(首选)或Python解压缩即可从ZIP存档中删除文件 嗨 我使用包含数百个高度压缩文本文件的大型ZIP文件。当我解压缩ZIP文件时,可能需要一段时间,并且很容易消耗高达20GB的磁盘空间。我想从这些ZIP文件中删除某些文件,而不必只解压缩和重新压缩我想要的文件 当然,这样做当然是可能的,但效率很低 我希望在java中这样做,但是会考虑Python < P> OK,我想我从www. java.Org找到了一个潜在的解决方案。它肯定会删除zip中的文件,我认为它不会解压缩任何东西

无需使用Java(首选)或Python解压缩即可从ZIP存档中删除文件

我使用包含数百个高度压缩文本文件的大型ZIP文件。当我解压缩ZIP文件时,可能需要一段时间,并且很容易消耗高达20GB的磁盘空间。我想从这些ZIP文件中删除某些文件,而不必只解压缩和重新压缩我想要的文件

当然,这样做当然是可能的,但效率很低


<>我希望在java中这样做,但是会考虑Python

< P> OK,我想我从www. java.Org找到了一个潜在的解决方案。它肯定会删除zip中的文件,我认为它不会解压缩任何东西。代码如下:

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();

}我没有代码来做这件事,但基本思想很简单,应该以同样的方式翻译成几乎任何语言。ZIP文件布局只是一系列表示文件的块(一个头,后面是压缩数据),最后是一个包含所有元数据的中心目录。过程如下:

  • 向前扫描文件,直到找到要删除的第一个文件
  • 向前扫描文件,直到找到不想删除的第一个文件或点击中心目录
  • 向前扫描文件,直到找到要删除的第一个文件或点击中心目录
  • 将在步骤3中找到的所有数据复制回步骤2中跳过的数据,直到找到另一个要删除的文件或点击中心目录
  • 除非你点击了中央目录,否则请转到步骤2
  • 将中心目录复制到停止复制的位置,保留已删除文件的条目,并更改偏移以反映每个文件的移动量
  • 有关ZIP文件结构的所有详细信息,请参阅

    正如bestsss所建议的,您可能希望执行到另一个文件的复制,以防止在发生故障时丢失数据。

    只有标准库的干净解决方案,但我不确定是否包含在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");   
            } 
        }
    }
    
    import java.util.*;
    导入java.net.URI;
    导入java.nio.file.Path;
    导入java.nio.file.*;
    导入java.nio.file.StandardCopyOption;
    公共类ZPFSDelete{
    公共静态void main(字符串[]args)引发异常{
    /*在HashMap*中定义ZIP文件系统属性
    Map zip_properties=new HashMap();
    /*我们想读取一个现有的ZIP文件,所以将其设置为False*/
    zip_properties.put(“创建”、“假”);
    /*指定要作为文件系统读取的ZIP文件的路径*/
    URI zip_disk=URI.create(“jar:file:/my_zip_file.zip”);
    /*创建ZIP文件系统*/
    try(FileSystem zipfs=FileSystems.newFileSystem(zip\u磁盘,zip\u属性)){
    /*获取ZIP文件内的路径以删除ZIP条目*/
    Path pathInZipfile=zipfs.getPath(“source.sql”);
    System.out.println(“即将从ZIP文件中删除条目”+pathInZipfile.toUri());
    /*执行删除*/
    文件。删除(pathInZipfile);
    System.out.println(“文件已成功删除”);
    } 
    }
    }
    
    是的,JAVA可以使用名为TRUEZIP的库

    TrueZIP是一个基于Java的虚拟文件系统(VFS),它支持客户端 执行CRUD(创建、读取、更新、删除)操作的应用程序 在归档文件上,就好像它们是虚拟目录一样,即使是嵌套的 在多线程环境中归档文件

    有关更多信息,请参阅下面的链接

    第1步:阅读此内容。步骤2:发布您尝试过的代码。@S.Lott:如果不先解压缩文件,这将无法工作。ZIP不是为快速更新而设计的,它涉及到重写整个文件,即使是简单的更改。与其删除这些引用,我建议您保留一个列出已删除文件的文件,以及另一个用于更改文件的ZIP或目录(如果需要的话)。一个通宵/离线过程可以重写该文件以反映所有更改。@Gabe:我不清楚“那不起作用”是什么意思。你能解释一下吗?看起来读一点有助于澄清这个问题。@S.Lott,当然,可以阅读zip的目录结构,不需要完全解压缩。也可以从zip中删除条目,而不完全重建它,但我不建议这样做。ZipOutputStream会重新创建文件,因此它会解压缩所有内容并将其压缩回来。我想知道你是否了解这个代码,临时文件在几英里前就可以看到了。每次读取1024字节也会特别无效。对-上面调用
    zin.read
    zout.write
    的代码分别进行解压缩和压缩。通过编写一些直接从文件流中读取并写入文件流的逻辑,您可以不费吹灰之力地做您想要做的事情。您需要避免对ZipInputStream和ZipOutStream进行读写操作。Gabe()的答案抓住了这个想法。如果你这样做,你很可能需要一个临时文件(以防止压缩过程中出现故障/错误)。因此,这个过程将通过不必要的(而且非常缓慢的)解压缩/压缩来重建文件。只是一个旁注-这不是一个答案,因为OP询问了Java或Python,但是…DotNetZip库可以做到这一点,对于.NET应用程序来说或多或少是透明的。当您读取zip文件时,会得到一组条目。在某些条目上调用
    .Remove()
    ,然后在zipfile上调用
    .Save()
    ,库将运行一系列步骤,这些步骤与此处描述的非常接近,只写入未标记为删除的条目。使用DotNetZip更新现有zip文件时