我设法找到两个使用Java压缩目录的代码片段:
public static void pack(final Path folder, final Path zipFilePath) throws IOException {
try (
FileOutputStream fos = new FileOutputStream(zipFilePath.toFile());
ZipOutputStream zos = new ZipOutputStream(fos)
) {
Files.walkFileTree(folder, new SimpleFileVisitor<Path>() {
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
zos.putNextEntry(new ZipEntry(folder.relativize(file).toString()));
Files.copy(file, zos);
zos.closeEntry();
return FileVisitResult.CONTINUE;
}
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
zos.putNextEntry(new ZipEntry(folder.relativize(dir).toString() + "/"));
zos.closeEntry();
return FileVisitResult.CONTINUE;
}
});
}
}
和
public static void pack(String sourceDirPath, String zipFilePath) throws IOException {
Path p = Files.createFile(Paths.get(zipFilePath));
try (ZipOutputStream zs = new ZipOutputStream(Files.newOutputStream(p))) {
Path pp = Paths.get(sourceDirPath);
Files.walk(pp)
.filter(path -> !Files.isDirectory(path))
.forEach(path -> {
ZipEntry zipEntry = new ZipEntry(pp.relativize(path).toString());
try {
zs.putNextEntry(zipEntry);
zs.write(Files.readAllBytes(path));
zs.closeEntry();
} catch (Exception e) {
System.err.println(e);
}
});
}
}
但是,对于这两个例子,我无法解释如何排除源目录中的某些子目录被包含在输出zip中。
有人可以伸出援手吗?
非常感谢你!
答案 0 :(得分:1)
简短的回答是在preVisitDirectory(...)
方法中定义目录过滤器,以便在它预先访问您要排除的目录时返回FileVisitResult.SKIP_SUBTREE
。
有关详情,请参阅Walking the File Tree的控制流程部分。
修改强>
根据要求,使用上面提供的代码进行示例实现。使用指向源目录(srcPath
)和Zip文件名(zipPath
)的路径创建它的实例。添加要排除的任何目录名称。例如,addDirExclude( "bin" )
将排除任何名为bin
的目录,其文件以及其下的任何子目录。
这是一个示例,旨在演示进一步控制文件树遍历的几种方法之一。 这不是生产质量代码;使用风险自负。
public class ZipWithExcludedDirs {
final private Path srcPath;
final private Path zipPath;
final private List<String> excludeList = new ArrayList<>();
public ZipWithExcludedDirs( Path srcPath, Path zipPath ) {
this.srcPath = srcPath;
this.zipPath = zipPath;
}
public void addDirExclude( String exDir ) {
excludeList.add( exDir );
}
public void pack() throws IOException {
try ( FileOutputStream fos = new FileOutputStream( zipPath.toFile() );
ZipOutputStream zos = new ZipOutputStream( fos ) ) {
Files.walkFileTree( srcPath, new SimpleFileVisitor<Path>() {
public FileVisitResult visitFile( Path file, BasicFileAttributes attrs )
throws IOException {
zos.putNextEntry( new ZipEntry( file.toString() ) );
Files.copy( file, zos );
zos.closeEntry();
return FileVisitResult.CONTINUE;
}
public FileVisitResult preVisitDirectory( Path dir, BasicFileAttributes attrs )
throws IOException {
String dirName = dir.getFileName().toString();
for ( String excl : excludeList )
if ( dirName.equals( excl ) )
return FileVisitResult.SKIP_SUBTREE;
zos.putNextEntry( new ZipEntry( dir.toString() + "/" ) );
zos.closeEntry();
return FileVisitResult.CONTINUE;
}
} );
}
}
}
编辑(部分Deux)
我已经编辑了上面的代码,以便它返回SKIP_SUBTREE
而不是SKIP_SIBLINGS
,这是我原来的,但由于某种原因而改变了。一瞥JavaDocs似乎表明SKIP_SUBTREE
和SKIP_SIBLINGS
对所访问的目录具有相同的效果。确实如此。但是SKIP_SIBLINGS
也会影响目录的兄弟(即在同一父目录中跟随它的文件和目录)。
此外,OP引用的原始文件walker代码会导致包含错误的工件。这是由于ZipEntry
路径的“相对化”。路径不应在SimpleFileVistor
中调整。如果存档需要相对或
绝对,然后原始srcPath
应该这样设置。