An open API service indexing awesome lists of open source software.

https://github.com/gotson/nightcompress


https://github.com/gotson/nightcompress

Last synced: 5 months ago
JSON representation

Awesome Lists containing this project

README

          

[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/gotson/NightCompress/ci.yml?branch=main&style=flat-square)](https://github.com/gotson/NightCompress/actions/workflows/ci.yml)
[![Maven Central](https://img.shields.io/maven-central/v/com.github.gotson.nightcompress/nightcompress?color=blue&style=flat-square&label=maven%20central)](https://search.maven.org/search?q=g:com.github.gotson.nightcompress)
![Maven Snapshot](https://img.shields.io/maven-metadata/v?metadataUrl=https%3A%2F%2Fcentral.sonatype.com%2Frepository%2Fmaven-snapshots%2Fcom%2Fgithub%2Fgotson%2Fnightcompress%2Fnightcompress%2Fmaven-metadata.xml&style=flat-square&label=maven%20snapshot&color=blue)

# NightCompress

A Java wrapper around [libarchive](https://libarchive.org/). NightCompress uses the Foreign Linker API
available since JDK 22 to access native libraries.

## How it works

NightCompress is released as a multi-release JAR:

- with Java < 22 as a no-op version that throws `UnsupportedOperationException` on any operation
- with Java 22+ all the features are available

This lets you add the dependency in your project whatever the JDK used, and still enable the feature at runtime if the required JDK is used.

## Requirements

In order for the JAR to run properly, you will need to:

- Run Java 22 with the following options:

```
--enable-native-access=ALL-UNNAMED
```

- Make sure the path to the directory containing the native libraries is contained in the Java system
property `java.library.path` (check
also [this](https://stackoverflow.com/questions/20038789/default-java-library-path)).
- For Linux, normally it works fine when installed from a package manager. You can add the libraries' path to
the `LD_LIBRARY_PATH` environment variable.
- For Mac, if using HomeBrew, you will need to set `JAVA_LIBRARY_PATH` to `/usr/local/lib/` or `/opt/homebrew/lib/`.

## Installation

### Gradle

```groovy
implementation "com.github.gotson.nightcompress:nightcompress:{version}"
```

### Gradle (Kotlin DSL)

```kotlin
implementation("com.github.gotson.nightcompress:nightcompress:{version}")
```

### Maven

```xml

com.github.gotson.nightcompress
nightcompress
{version}

```

## Usage

### Check if the library is available

```java
try {
if (Archive.isAvailable()) {
// do stuff
}
} catch(Exception e) {
// to be on the safe side
}
```

### Extract from a `Path` to an `OutputStream`
```java
// Assuming you already have a Path pointing to the archive file and an OutputStream for writing to
Archive archive = new Archive(path);
while (archive.getNextEntry() != null) {
try (InputStream is = archive.getInputStream()) {
is.transferTo(outputStream);
}
}

// Assuming you already know which entry you want to extract
try (InputStream is = Archive.getInputStream(path, entryName)) {
is.transferTo(outputStream);
}
```

### Specify Compression, Filter, and Format

`libarchive` supports various [formats](https://github.com/libarchive/libarchive/wiki/LibarchiveFormats). You can specify the compression, filter, and formats you want to enable when calling the `Archive` constructor, or the static functions `Archive.getEntries` and `Archive.getInputStream`.

By default, all will be enabled.

This can cause issues if you have archives within archives though. For example, if you have a RAR file containing a ZIP file, when all is enabled, `libarchive` would produce entries of the inner ZIP file, instead of the ZIP file entry itself.

```java
// Enable RAR5 only
Archive archive = new Archive(path, Set.of(ReadSupportCompression.NONE), Set.of(ReadSupportFilter.NONE), Set.of(ReadSupportFormat.RAR5));

Archive.getInputStream(path, Set.of(ReadSupportCompression.NONE), Set.of(ReadSupportFilter.NONE), Set.of(ReadSupportFormat.RAR5), entryName)
```

## Configuration

NightCompress allows for some tuning using System Properties:

- Options for `Archive#getInputStream(Path)`:
- `nightcompress.extractor.buffer-size`: accepts any positive integer. Defaults to `32 * 1024`.
- Sets the maximum size used for the dynamic byte buffer in the `PipedInputStream`.
- `nightcompress.extractor.use-executor`: accepts either `true` or `false`. Defaults to `true`.
- If `true`, it uses a cached thread pool for extracting the contents, which is generally faster.
- If `false`, it will create a new thread on each call. This may be slower, but may require slightly less memory.
- Options for tuning the thread pool:
- `nightcompress.extractor.max-threads`: accepts any positive integer. Defaults to `2^31`.
- Sets the maximum number of threads to be used in the pool. By default, there is no hard limit on the number
of threads, but they are only created when needed, so the maximum should not exceed the number of threads
calling this method at any given moment. Use this if you need to restrict the number of threads.
- `nightcompress.extractor.thread-keep-alive-seconds`: accepts any positive integer. Defaults to `5`.
- Sets the number of seconds a thread can be kept alive in the pool, waiting for a next extraction operation.
After that time, the thread may be stopped.

## Implementation notes

The `panama` package bindings were generated using:
- jextract 22
- from the https://github.com/libarchive/libarchive/ repository, version 3.5.0
- based on a synthetic header file:
```
#include "archive.h"
#include "archive_entry.h"
```