Compress4J

Overview

Compress4J is an up-to-date fork of JArchiveLib.

It’s a simple archiving and compression library for Java that provides a thin and easy-to-use API layer on top of the powerful and feature-rich org.apache.commons.compress.

Compress4J is a Java library dedicated to simplifying the handling of various data compressors formats. Its primary goal is to provide developers with a unified and straightforward API for compressing and decompressing files and data streams, regardless of the underlying algorithm being used.

Inspired by the need for a consistent way to interact with different compression techniques, Compress4J abstracts the specific implementations behind common interfaces, making it easier to incorporate compression into Java applications or to switch between compression formats.

Getting Started

To use Compress4J in your Java project, you typically need to include it as a dependency in your build configuration.

  • Maven

  • Gradle Groovy

  • Gradle Kotlin

<dependency>
    <groupId>io.github.compress4j</groupId>
    <artifactId>compress4j</artifactId>
    <version>YOUR_VERSION</version>
</dependency>
dependencies {
    implementation 'io.github.compress4j:compress4j:YOUR_VERSION'
}
dependencies {
    implementation("io.github.compress4j:compress4j:YOUR_VERSION")
}

Core Concepts

The library’s design centers around a few key components:

  • Compressor Interface: Defines the contract for compressing an OutputStream. Implementations handle the specifics of a particular compression algorithm.

  • Decompressor Interface: Defines the contract for decompressing an InputStream. Implementations handle the specifics of decompressing data from a particular format.

  • ArchiveCreator: A factory class used to obtain instances of Compressor for supported algorithms. This promotes loose coupling and simplifies the creation process.

  • ArchiveExtractor: A factory class used to obtain instances of Decompressor for supported algorithms.

By using these factories, developers can request a compressor or decompressor for a desired algorithm (e.g., Gzip, Zstandard) without needing to know the specific implementation class names.

Supported Formats

Compress4J supports a variety of common stream compression formats. The goal is to provide access to efficient and widely used algorithms, including (but not necessarily limited to):

  • AR (.a, .ar)

  • CPIO (.cpio)

  • Deflate (.deflate)

  • Bzip2 (.bz2)

  • Gzip (.gz, gzip)

  • Pack200 (.pack)

  • Tar (.tar, tar.bz2, tbz2, tar.gz, tgz, tar.xz, txz)

  • XZ (.xz)

  • Zip (.zip)

  • Zip (.zip)

The library often achieves this by integrating with robust, high-performance backend libraries (like zstd-jni for Zstandard) or by providing its own implementations.

Some compression formats may require additional support libraries to be included in your project. Please refer to the Additional Formats for details on any extra dependencies needed for specific formats.

Extracting Untrusted Archives

Path traversal is always rejected: entry paths are resolved canonically against the output directory, so both ../ entries and writes that would follow a symlink out of the output directory fail with an IOException.

Two things are not restricted by default, because they are legitimate in archives you produced yourself:

  • Escaping symlinks. Use escapingSymlinkPolicy(DISALLOW) to reject them, or RELATIVIZE_ABSOLUTE to rewrite absolute targets so they stay inside the output directory.

  • How far an archive may expand. Use maxEntries, maxEntrySize and maxTotalSize to bound it. Breaching a limit throws ArchiveLimitExceededException, which an error handler cannot suppress.

try (TarGzArchiveExtractor extractor = TarGzArchiveExtractor.builder(Path.of("untrusted.tar.gz"))
        .escapingSymlinkPolicy(DISALLOW)
        .maxEntries(10_000)
        .maxEntrySize(100L * 1024 * 1024)
        .maxTotalSize(1024L * 1024 * 1024)
        .build()) {
    extractor.extract(Path.of("outputDir"));
}

Key Goals

  • Simplicity: Offer an easy-to-understand API for common compression/decompression tasks.

  • Consistency: Provide a uniform interaction model across different compression algorithms.

  • Abstraction: Hide the complexities of individual compression library APIs from the end-user.

  • Extensibility: Facilitate the addition of support for new compression formats in the future.