从ZIP存档中删除文件,而无需使用Java或Python进行解压缩
无需使用Java(首选)或Python解压缩即可从ZIP存档中删除文件 嗨 我使用包含数百个高度压缩文本文件的大型ZIP文件。当我解压缩ZIP文件时,可能需要一段时间,并且很容易消耗高达20GB的磁盘空间。我想从这些ZIP文件中删除某些文件,而不必只解压缩和重新压缩我想要的文件 当然,这样做当然是可能的,但效率很低从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 < 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文件布局只是一系列表示文件的块(一个头,后面是压缩数据),最后是一个包含所有元数据的中心目录。过程如下:
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文件时