[英]Zipping Folder with Java but Excluding Certain Sub-directories
我設法找到了兩個示例代碼片段,用於使用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中排除源目錄中的某些子目錄。
有人可以幫我嗎?
非常感謝!
簡短的答案是在preVisitDirectory(...)
方法中定義目錄過濾器, preVisitDirectory(...)
在每次訪問您要排除的目錄時都返回FileVisitResult.SKIP_SUBTREE
。
有關更多詳細信息,請參見遍歷文件樹的控制流部分。
編輯:
根據要求,使用上述提供的代碼的示例實現。 使用源目錄( 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;
}
} );
}
}
}
編輯(零件雙聯)
我已經編輯了上面的代碼,使它返回的是SKIP_SUBTREE
而不是SKIP_SIBLINGS
,這是我最初的設置,但是由於某些原因而更改。 乍一看JavaDocs似乎表明SKIP_SUBTREE
和SKIP_SIBLINGS
對被訪問的目錄具有相同的作用。 是的 但是, SKIP_SIBLINGS
也影響目錄的同級 (即,在同一父目錄中跟隨該目錄的文件和目錄)。
此外,OP引用的原始文件遍歷器代碼會導致包含錯誤的工件。 這是由於ZipEntry
路徑的“相對化”。 路徑不應在SimpleFileVistor
進行調整。 如果需要存檔是相對存檔或絕對存檔,則原始srcPath
應該設置為相對存檔或絕對存檔。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.