7z
7z is the archive format of the 7-Zip utility. Compress4J creates 7z archives and extracts them, including password-protected ones.
Extraction goes through the same guards as every other format: path traversal is rejected, and escapingSymlinkPolicy and the limits (limits(…), maxEntries, maxEntrySize, maxTotalSize, maxRatio) apply. See Security.
Example Usage
try (SevenZArchiveCreator sevenZCreator =
SevenZArchiveCreator.builder(Path.of("example.7z")).build()) {
sevenZCreator.addFile(Path.of("path/to/file.txt"));
sevenZCreator.addDirectoryRecursively(Path.of("sourceDir"));
}
try (SevenZArchiveExtractor sevenZExtractor = SevenZArchiveExtractor.builder(Path.of("example.7z"))
.overwrite(true)
.stripComponents(1)
.filter(entry -> entry.name().endsWith(".txt"))
.errorHandler((entry, exception) -> SKIP)
.escapingSymlinkPolicy(EscapingSymlinkPolicy.DISALLOW)
.build()) {
sevenZExtractor.extract(Path.of("outputDir"));
}
try (SevenZArchiveExtractor sevenZExtractor = SevenZArchiveExtractor.builder(Path.of("encrypted.7z"))
.password("secret".toCharArray())
.maxEntries(10_000)
.maxTotalSize(1024L * 1024 * 1024)
.build()) {
sevenZExtractor.extract(Path.of("outputDir"));
}
Notes
-
The creator writes to a file path or a
SeekableByteChannel, because 7z must seek back to patch its header. A channel is written from offset 0. -
The creator does not encrypt. Only extraction accepts a password.
-
A symbolic link is stored the way p7zip stores it, as a Unix-mode entry whose content is the link target, and is restored as a symlink on extraction.
-
A wrong or missing password fails with an
IOException.
long maxArchiveSize = 512L * 1024 * 1024;
Files.createDirectories(outputDir);
Path spool = Files.createTempFile(
outputDir.toAbsolutePath().getParent(),
"archive",
".7z"); // 7z needs random access, so spool the stream to disk
try {
try (OutputStream out = Files.newOutputStream(spool)) {
byte[] buffer = new byte[8192];
long copied = 0;
for (int read; (read = download.read(buffer)) != -1; ) {
copied += read;
if (copied > maxArchiveSize) {
throw new IOException("Archive exceeds " + maxArchiveSize + " bytes");
}
out.write(buffer, 0, read);
}
}
try (var extractor = SevenZArchiveExtractor.builder(spool)
.maxEntries(10_000)
.maxEntrySize(100L * 1024 * 1024)
.maxTotalSize(1024L * 1024 * 1024)
.build()) {
extractor.extract(outputDir);
}
} finally {
Files.deleteIfExists(spool);
}
7z keeps its header at the end of the archive, so it reads only from a file or a SeekableByteChannel. The example spools the stream to a temp file outside the output directory, stops the copy at a size cap, and applies extraction limits to the result. Choose both bounds for your input.
|