用Java重命名Zip文件中的文件/文件夹?

我有一个包含文件夹结构的zip文件

  • 主文件夹/
    • subFolder1 /
    • subFolder2 /
    • subFolder3 /
      • file3.1
      • file3.2

我想重命名文件夹main-folder让我们说使用Java在那个非常zip文件里面的versionXY

有没有比提取整个zip文件并使用新文件夹名称重新创建新文件更简单的方法?

Zip是一种存档格式,因此变异通常涉及重写文件。

拉链的一些特殊function也会妨碍(拉链充满“function”)。 除了归档末尾的中央目录外,每个组件文件前面都有其文件名。 Zip没有目录的概念 – 文件名只是碰巧包含“/”字符的字符串(以及诸如“../”的子字符串。

因此,您确实需要使用ZipInputStreamZipOutputStream复制文件,然后重命名。 如果你真的想要你可以重写文件来做你自己的缓冲。 该过程确实导致内容被重新压缩,因为标准API无法以压缩forms获取数据。

我知道你问过Java但是出于档案目的,我想我会提供关于.NET的说明。

DotNetZip是一个用于zip文件的.NET库,允许重命名条目。 正如Tom Hawtin的回复所述,目录不是zip文件元数据中的第一类实体,因此,我知道没有任何zip库可以公开“重命名目录”动词。 但是有些库允许您重命名具有指示特定目录的名称的所有条目,从而为您提供所需的结果。

在DotNetZip中,它看起来像这样:

  var regex = new Regex("/OldDirName/.*$"); int renameCount= 0; using (ZipFile zip = ZipFile.Read(ExistingZipFile)) { foreach (ZipEntry e in zip) { if (regex.IsMatch(e.FileName)) { // rename here e.FileName = e.FileName.Replace("/OldDirName/", "/NewDirName/"); renameCount++; } } if (renameCount > 0) { zip.Comment = String.Format("This archive has been modified. {0} entries have been renamed.", renameCount); // any changes to the entries are made permanent by Save() zip.Save(); // could also save to a new zip file here } } 

您还可以在using子句中添加或删除条目。

如果保存到同一文件,则DotNetZip仅重写已更改的元数据 – 重命名条目的条目标题和中央目录记录,这样可以节省大型归档的时间。 如果保存到新文件或流,则会写入所有zip数据。

我想你可以使用Commons Compress找到这个任务的帮助,特别是ZipArchiveEntry

这就是诀窍。 由于它仅适用于中央目录而不是文件,因此速度极快。

 // rezip( zipfile, "/main-folder", "/versionXY" ); import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.nio.file.FileSystem; import java.nio.file.FileSystems; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.LinkOption; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; protected void rezip( String zipfile, String olddir, String newdir ) { Path zipFilePath = Paths.get( zipfile ); try (FileSystem fs = FileSystems.newFileSystem( zipFilePath, null )) { Path oldpathInsideZipPath = fs.getPath( olddir ); if( ! Files.exists( Paths.get( newdir ) ) ) Files.createDirectory( Paths.get( newdir ) ); if ( Files.exists( oldpathInsideZipPath, LinkOption.NOFOLLOW_LINKS ) ) { Files.walkFileTree(oldpathInsideZipPath, new SimpleFileVisitor() { @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { if( file.toString().indexOf( olddir ) > -1 ){ String a = file.toString().replaceAll( olddir, newdir ); Path b = fs.getPath( a ); if( ! Files.exists( b.getParent() ) ){ Files.createDirectories( b.getParent() ); } Files.move( file, b, LinkOption.NOFOLLOW_LINKS ); } return FileVisitResult.CONTINUE; } @Override public FileVisitResult postVisitDirectory(Path dir, IOException e) throws IOException { if (e == null) { Files.delete(dir); return FileVisitResult.CONTINUE; } else { // directory iteration failed throw e; } } }); } fs.close(); } catch ( Exception e ) { e.printStackTrace(); } }