我有一个包含文件夹结构的zip文件,如
我想重命名文件夹main-folder
,让我们在使用Java的zip文件中说versionXY
。
是否有一种比使用新文件夹名称提取整个zip文件并重新创建新文件更简单的方法?
答案 0 :(得分:4)
Zip是一种存档格式,因此变异通常涉及重写文件。
拉链的一些特殊功能也会妨碍(拉链充满“功能”)。除了归档末尾的中央目录外,每个组件文件前面都有其文件名。 Zip没有目录的概念 - 文件名只是恰好包含“/”字符的字符串(以及诸如“../".
的子字符串因此,您确实需要使用ZipInputStream
和ZipOutputStream
复制文件,然后重命名。如果你真的想要你可以重写文件来做你自己的缓冲。该过程确实导致内容被重新压缩,因为标准API无法以压缩形式获取数据。
答案 1 :(得分:4)
我知道你问过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数据。
答案 2 :(得分:3)
我认为您可以使用Commons Compress找到此任务的帮助,尤其是ZipArchiveEntry
答案 3 :(得分:0)
这就是诀窍。因为它仅适用于中央目录而不是文件,因此速度极快。
// 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<Path>() {
@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();
}
}