Reputation: 3
I managed to find two example snippets of code for zipping a directory with 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;
}
});
}
}
and
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);
}
});
}
}
But, for both examples, I can't for the life of me figure out how to exclude certain sub-directories within the source directories from being included in the output zip.
Could somebody lend me a hand?
Thank you so much!
Upvotes: 0
Views: 1895
Reputation: 3507
The short answer is to define your directory filter in the preVisitDirectory(...)
method such that it returns FileVisitResult.SKIP_SUBTREE
whenever it pre-visits a directory that you would like to exclude.
For more details, see the Controlling the Flow section of Walking the File Tree.
Edit:
As requested, a sample implementation using the above provided code. Create an instance of it with paths to the source directory (srcPath
) and Zip file name (zipPath
). Add any directory names to be excluded. For example, addDirExclude( "bin" )
would exclude any directory named bin
, its files, and any sub-directories thereunder.
This is an example, intended to demonstration one of several ways to further control a file tree walk. This is not production quality code; use at your own risk.
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;
}
} );
}
}
}
Edit (Part Deux)
I have edited the above code such that it returns SKIP_SUBTREE
instead of SKIP_SIBLINGS
, which is what I had originally, but changed for some reason. A glance at the JavaDocs appears to indicate that SKIP_SUBTREE
and SKIP_SIBLINGS
have the same effect on the directory being visited. It does. However SKIP_SIBLINGS
also affects siblings of the directory (i.e. files and directories that follow it in the same parent directory).
Furthermore, the original file walker code referenced by OP, causes an erroneous artifact to be included. This was due to the "relativizing" of the ZipEntry
path. Paths should not adjusted in SimpleFileVistor
. If there is a need for an archive to be relative or
absolute, then the original srcPath
should set as such.
Upvotes: 1