|
This version is still in development and is not considered stable yet. For the latest stable version, please use Compress4J 5.x! |
Migrating from 4.x to 5.0
Each table lists the 4.x API on the left and its 5.0 replacement on the right. See Security for the new defaults in depth.
Safer defaults
| 4.x | 5.0 |
|---|---|
|
The default is |
No default limits |
|
|
|
Any negative |
Only |
|
Every reader enforces |
Path traversal and escaping symlinks threw a plain |
|
|
|
Behaviour change for 4.x users. An errorHandler that returned SKIP or SKIP_ALL used to continue past a traversal or escaping-symlink entry. In 5.0 that entry aborts the extraction with UnsafeEntryException. Code that relied on skipping such entries must stop doing so or filter them out before extraction.
|
-
DISALLOW, the default, re-checks every symlink an extraction created once it finishes. Links that escape through later entries are removed and extraction fails withUnsafeEntryException. -
RELATIVIZE_ABSOLUTErewrites absolute targets under the output directory, then rejects any target that still escapes. 4.x accepted relative escapes. -
maxEntriescounts entries afterstripComponentsand the filter. Skipped unsupported or filtered entries are not counted, and theunsupportedEntryHandlerruns once per skipped entry without a bound. -
A highly compressible but legitimate archive, such as a log archive, can exceed ratio 100. The exception names
maxRatio. -
Reading
.xzand.lzmawithoutmemoryLimitKiBis now capped at 256 MiB, inDecompressorandTarArchiveExtractor.memoryLimitKiB(Integer.MAX_VALUE)lifts the cap. -
The public stream-taking constructors of 4.x are gone, so every extractor is built through a builder and enforces the limits.
Errors
| 4.x | 5.0 |
|---|---|
|
Removed. Retry outside the extractor: the entry stream is already consumed. |
|
|
|
|
|
Throws |
Parser |
|
|
|
-
Corrupt archives and corrupt compressed data throw
IOException. Callbacks (filter, error handler, post-processor, unsupported-entry handler) andMissingArchiveDependencyExceptionstill propagate unchanged. -
A
RuntimeExceptionfrom a caller-supplied source stream is reported as corrupt input. -
The error handler is consulted for parser failures while reading entry content. In 4.x extraction aborted.
-
stream()surfaces parser failures asUncheckedIOExceptionwrapping theIOException. -
A
.Zheader demanding a code table above 64 MiB fails withIOException.
Reading archives
| 4.x | 5.0 |
|---|---|
|
Top-level |
|
|
|
|
|
|
|
The matching builder option, e.g. |
|
|
|
|
Record patterns over |
|
|
|
Devices, FIFOs, sockets and hard links extracted as empty or regular files, or dropped silently (tar) |
Skipped and reported to |
An extractor reads its archive once: call either stream() or extract(), once.
Zips written by 4.x still extract their symlinks as regular files. Only archives re-created with 5.0 contain real symlinks.
Writing archives
| 4.x | 5.0 |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
A symlink or directory |
|
|
|
|
|
|
|
-
builder.filter(null)throwsNullPointerException; it no longer resets the filter. The filter may run more than once per entry, so keep it free of side effects. -
After a write fails, the creator is failed: further adds throw
IllegalStateException.close()still releases the sink. -
Every format enforces a file’s declared size. Too many or too few bytes throw an
IOExceptionnaming the entry. -
The creator strips leading slashes from entry names and converts
\to/. Names with a NUL, a drive prefix such asC:or a..segment throwUnsafeEntryException. A name made only of slashes throwsIllegalArgumentException. A walked file literally named..\xabortsaddDirectoryRecursively. -
Sockets, FIFOs and devices are rejected as entry sources with
IllegalArgumentException, including duringaddDirectoryRecursively. -
addDirectoryRecursivelystores directory permissions. On a file system without a POSIX view (Windows, zip FS), path modes stay unknown and the format default applies, instead of DOS flags. -
ar and cpio symlink targets over 4096 bytes fail with
IOException; zip caps symlink targets too.
Sources and sinks
| 4.x | 5.0 |
|---|---|
|
|
|
Removed; use |
|
|
|
|
Public constructors of the archive classes, including the stream-taking ones |
Removed; every format class is |
Nested |
Nested |
|
Removed. Commons Compress streams no longer appear in the API. |
|
Removed. |
-
New:
builder(SeekableByteChannel)on every format, andZipArchiveExtractor.streaming(InputStream). See format capabilities. -
Zip streaming mode reports mode
0, extracts symlinks as regular files holding the target, and may leave an entry’ssize()empty. -
7z needs random access. To read a stream, copy it into a
SeekableInMemoryByteChannelor a temp file; see 7z. -
SevenZArchiveCreator.builder(Path)creates its file atbuild(), not when the builder is made. The channel creator writes from offset 0. -
ArchiveExtractorandArchiveCreatorlose their type parameter. Their builders becomeArchiveExtractor.Builder<B, E>andArchiveCreator.Builder<B, C>.
Compressors
| 4.x | 5.0 |
|---|---|
|
|
|
|
Codec options on the codec builders |
Options on the |
|
|
Packages |
Removed, with the abstract bases that became |
No limits on decompression |
|
-
Detection reads gzip, bzip2, xz, zstd, lz4-framed,
.Zand snappy-framed by magic number. Concatenated gzip, bzip2, xz and framed LZ4 members are decompressed; zstd, framed Snappy and.Zare not verified to read them. LZMA has no magic number: passCompression.lzma(). -
Decompressornever detects Pack200, and tar rejectsCompression.pack200(). Pass Pack200 explicitly; it decodes eagerly inbuild(), so the limits do not bound it; use it for trusted input only. -
CompressorandDecompressoropen their path, channel or stream inbuild().
Tar
| 4.x | 5.0 |
|---|---|
|
|
|
|
|
Removed. |
|
|
|
|
|
|
Bad header checksum, or 1 to 511 bytes of input, read as an empty archive |
|
Tar entries on Windows reporting mode |
Archived modes on every host. |
Other formats
| 4.x | 5.0 |
|---|---|
|
|
arj and dump |
|
Zip |
|
Zip |
|
Zip |
|
Zip |
|
Zip |
|
New in 5.0: SevenZArchiveCreator.builder(…).contentCompression(SevenZMethod) with the SevenZMethod enum COPY, LZMA2, LZMA, BZIP2 and DEFLATE.
The zip creator’s compressionMethod, comment, zip64 and encoding reject null with NullPointerException; so do the 7z creator’s contentCompression and the 7z extractor’s password.
File modes
| 4.x | 5.0 |
|---|---|
Windows extraction marked executable files read-only |
A file is read-only only when its owner-write bit is missing. Hidden is never set and directories are never marked read-only. |
Directory modes applied as each directory appeared |
Applied after all entries, deepest first. After creation a directory keeps an interim mode of the archive’s permission bits plus owner-rwx, so a read-only directory cannot block its files. An aborted extraction leaves directories owner-writable; the group and other bits stay within the archive’s grant. A |
Mode |
Files and directories keep the host defaults. |
An entry path holding a symlink was overwritten through the link |
The write fails and goes to the error handler. |
Removed APIs and dependencies
-
ArchiveExtractor.setAttributes,ArchiveExtractor.isIsOsWindows,ArchiveCreator.mode,ArchiveCreator.isIsOsWindowsandArchiveCreator.sanitiseName. -
FileUtils.DOS_READ_ONLY,DOS_HIDDENandNO_MODE;archivers.Compressor,utils.StringUtilandutils.ExcludeFromJacocoGeneratedReport. Theutilspackage is now the unexportedinternal.util. -
Custom formats: the format classes are
final, andArchiveExtractorandArchiveCreatorcannot be subclassed outside the library. The reader and writer SPI (internal.archive) is not exported from the module. Their constructors take internal types, andnextEntry,openEntryStream,closeEntryStream,readEntryContent,writeDirectoryEntryandwriteFileEntryare gone. -
MissingArchiveDependencyExceptionisfinal. -
commons-compress and commons-io are not
apidependencies and no module requires them transitively. They move to runtime scope in the published POM. Code that uses their types declares the dependency andrequires org.apache.commons.compressororg.apache.commons.ioitself.EntrySource.Filecontent is anEntrySource.ContentSupplierandzstdInputStreamFactorytakes aZipArchiveExtractor.ZstdStreamFactory, where both took commons-io function types (IOSupplier<InputStream>andIOFunction<InputStream, InputStream>). Lambdas and method references compile unchanged; a variable typed with the commons-io type, or anIOSupplierpassed fromcontent(), must change to the new type. -
jakarta.annotation-apiis no longer a dependency. Compress4J requires the JSpecify module (org.jspecify) and every exported package is@NullMarked, so Kotlin and NullAway see non-null parameters and return types.