
Implements compression and archive formats in pure common code, offering gzip/zlib/deflate, LZ4, Snappy decoding, ZIP/TAR/ar/cpio readers, checksums, sniffing, whole-array API and PathGuard.
Compression and archive formats in pure Kotlin, for Kotlin Multiplatform. Gunzip a buffer or read a ZIP on iOS and in the browser, as well as on the JVM, from one shared codebase.
AI tools wrote much of the code, tests and documentation in this project, under the direction and review of its author.
Documentation: a guide for each task, the format tables and the limits.
java.util.zip exists on the JVM and Android and nowhere else. A Kotlin Multiplatform project
that reads or writes archives usually adds a cinterop binding on iOS and a JavaScript shim on
the web, which means a native build and a different code path for each target. ArchiveKodec
implements the formats in commonMain instead. There is no JNI, no cinterop and no native
binary, and the core artifact depends on kotlin-stdlib and nothing else.
0.2.0 is not published to Maven Central yet. These are the coordinates it will use:
kotlin {
sourceSets {
commonMain.dependencies {
implementation("io.github.yuroyami:archivekodec:0.2.0")
// Optional: a file source, extract and kotlinx-io adapters.
implementation("io.github.yuroyami:archivekodec-io:0.2.0")
}
// Optional: AES for encrypted ZIP and 7z archives. Not on JS or Wasm.
jvmMain.dependencies {
implementation("io.github.yuroyami:archivekodec-crypto:0.2.0")
}
}
}The libraries need Kotlin 2.1 or newer, Java 8 or newer on the JVM and Android minSdk 21.
Install covers the Kotlin Toolchain and Maven. 0.1.0 is on Maven
Central under the older name io.github.yuroyami:kitearchive.
val gz = ArchiveKodec.gzip.compress(bytes)
val raw = ArchiveKodec.deflate.compress(bytes)
val back = ArchiveKodec.decompress(gz) // detects gzip, zlib, bzip2, xz, zstd, LZ4 and framed SnappyEvery codec takes a ByteArray and returns one. DEFLATE, zlib and gzip can also stream their
output to a sink. See Compression.
ArchiveKodec.open(bytes).use { reader ->
for (entry in reader.entries()) {
if (entry.isDirectory) continue
val content = reader.read(entry)
val path = PathGuard.sanitize(entry.name) // a safe relative path for this entry
}
}open detects the format and removes one gzip layer, so a .tar.gz opens in one call. A
listing refuses names such as ../../etc/passwd by default, but always build the output path
with PathGuard.sanitize. See Reading archives and
Entry names and Zip-Slip.
val zip = ZipWriter.write(
listOf(
ZipWriter.FileSpec("readme.txt", text, ZipMethod.STORED),
ZipWriter.FileSpec("data.bin", payload), // deflated
),
)TAR, GNU ar and cpio have writers too. See Writing archives.
ArchiveKodec.open(FileRandomAccessSource(path)).use { reader ->
reader.extract(reader.entries()) { entry ->
SystemFileSystem.sink(Path(outDir, PathGuard.sanitize(entry.name)))
}
}archivekodec-io reads the file on demand, so a large archive never sits in memory.
extract reports progress, stops when its coroutine is cancelled and skips symbolic links by
default. See Files and extraction.
Encrypted archives, limits and custom codecs and formats. Java, Swift and JavaScript have their own pages: Java, Swift and JavaScript and TypeScript.
Format support lists what each codec and reader handles, and what it refuses.
| Family | Targets |
|---|---|
| Android, JVM | Android (minSdk 21), jvm (Java 8 bytecode) |
| Apple |
iosArm64, iosSimulatorArm64, iosX64, macosArm64, tvosArm64, tvosSimulatorArm64, watchosArm32, watchosArm64, watchosDeviceArm64, watchosSimulatorArm64
|
| Other native |
linuxX64, linuxArm64, mingwX64, androidNativeArm32, androidNativeArm64, androidNativeX86, androidNativeX64
|
| Web |
js and wasmJs (browser and Node), wasmWasi (Node) |
The core and archivekodec-io build for every target in the table. archivekodec-crypto
builds for all of them except js, wasmJs and wasmWasi. In a browser and on WASI the file
source cannot open a file, so read the file into a ByteArray there.
ByteArray.
ZIP members that are stored, DEFLATE or Deflate64 can stream to a sink instead.Codec and ArchiveReader can gain members, so implementing
them needs an opt-in.CONTRIBUTING.md covers the build, the tests and the CI lanes. Open work is in GitHub Issues.
Apache-2.0. See LICENSE.
ArchiveKodec combines implementations of the format specifications with ports of permissively
licensed code. The inflate path is an altered Kotlin translation of Mark Adler's zlib-licensed
puff, and the encoder's canonical Huffman codes follow zlib's trees.c. PPMd is ported from
the public-domain Ppmd7.c and Ppmd8.c of Igor Pavlov's LZMA SDK. NOTICE and
reference/REFERENCES.md record the origins and licenses.
RAR archives are read from RARLAB's published format description, not from UnRAR source, and ArchiveKodec will never create RAR archives.
Part of the Kite family: KiteCore, KitePDF, ImageKodec, AudioKodec, KiteQR.
Compression and archive formats in pure Kotlin, for Kotlin Multiplatform. Gunzip a buffer or read a ZIP on iOS and in the browser, as well as on the JVM, from one shared codebase.
AI tools wrote much of the code, tests and documentation in this project, under the direction and review of its author.
Documentation: a guide for each task, the format tables and the limits.
java.util.zip exists on the JVM and Android and nowhere else. A Kotlin Multiplatform project
that reads or writes archives usually adds a cinterop binding on iOS and a JavaScript shim on
the web, which means a native build and a different code path for each target. ArchiveKodec
implements the formats in commonMain instead. There is no JNI, no cinterop and no native
binary, and the core artifact depends on kotlin-stdlib and nothing else.
0.2.0 is not published to Maven Central yet. These are the coordinates it will use:
kotlin {
sourceSets {
commonMain.dependencies {
implementation("io.github.yuroyami:archivekodec:0.2.0")
// Optional: a file source, extract and kotlinx-io adapters.
implementation("io.github.yuroyami:archivekodec-io:0.2.0")
}
// Optional: AES for encrypted ZIP and 7z archives. Not on JS or Wasm.
jvmMain.dependencies {
implementation("io.github.yuroyami:archivekodec-crypto:0.2.0")
}
}
}The libraries need Kotlin 2.1 or newer, Java 8 or newer on the JVM and Android minSdk 21.
Install covers the Kotlin Toolchain and Maven. 0.1.0 is on Maven
Central under the older name io.github.yuroyami:kitearchive.
val gz = ArchiveKodec.gzip.compress(bytes)
val raw = ArchiveKodec.deflate.compress(bytes)
val back = ArchiveKodec.decompress(gz) // detects gzip, zlib, bzip2, xz, zstd, LZ4 and framed SnappyEvery codec takes a ByteArray and returns one. DEFLATE, zlib and gzip can also stream their
output to a sink. See Compression.
ArchiveKodec.open(bytes).use { reader ->
for (entry in reader.entries()) {
if (entry.isDirectory) continue
val content = reader.read(entry)
val path = PathGuard.sanitize(entry.name) // a safe relative path for this entry
}
}open detects the format and removes one gzip layer, so a .tar.gz opens in one call. A
listing refuses names such as ../../etc/passwd by default, but always build the output path
with PathGuard.sanitize. See Reading archives and
Entry names and Zip-Slip.
val zip = ZipWriter.write(
listOf(
ZipWriter.FileSpec("readme.txt", text, ZipMethod.STORED),
ZipWriter.FileSpec("data.bin", payload), // deflated
),
)TAR, GNU ar and cpio have writers too. See Writing archives.
ArchiveKodec.open(FileRandomAccessSource(path)).use { reader ->
reader.extract(reader.entries()) { entry ->
SystemFileSystem.sink(Path(outDir, PathGuard.sanitize(entry.name)))
}
}archivekodec-io reads the file on demand, so a large archive never sits in memory.
extract reports progress, stops when its coroutine is cancelled and skips symbolic links by
default. See Files and extraction.
Encrypted archives, limits and custom codecs and formats. Java, Swift and JavaScript have their own pages: Java, Swift and JavaScript and TypeScript.
Format support lists what each codec and reader handles, and what it refuses.
| Family | Targets |
|---|---|
| Android, JVM | Android (minSdk 21), jvm (Java 8 bytecode) |
| Apple |
iosArm64, iosSimulatorArm64, iosX64, macosArm64, tvosArm64, tvosSimulatorArm64, watchosArm32, watchosArm64, watchosDeviceArm64, watchosSimulatorArm64
|
| Other native |
linuxX64, linuxArm64, mingwX64, androidNativeArm32, androidNativeArm64, androidNativeX86, androidNativeX64
|
| Web |
js and wasmJs (browser and Node), wasmWasi (Node) |
The core and archivekodec-io build for every target in the table. archivekodec-crypto
builds for all of them except js, wasmJs and wasmWasi. In a browser and on WASI the file
source cannot open a file, so read the file into a ByteArray there.
ByteArray.
ZIP members that are stored, DEFLATE or Deflate64 can stream to a sink instead.Codec and ArchiveReader can gain members, so implementing
them needs an opt-in.CONTRIBUTING.md covers the build, the tests and the CI lanes. Open work is in GitHub Issues.
Apache-2.0. See LICENSE.
ArchiveKodec combines implementations of the format specifications with ports of permissively
licensed code. The inflate path is an altered Kotlin translation of Mark Adler's zlib-licensed
puff, and the encoder's canonical Huffman codes follow zlib's trees.c. PPMd is ported from
the public-domain Ppmd7.c and Ppmd8.c of Igor Pavlov's LZMA SDK. NOTICE and
reference/REFERENCES.md record the origins and licenses.
RAR archives are read from RARLAB's published format description, not from UnRAR source, and ArchiveKodec will never create RAR archives.
Part of the Kite family: KiteCore, KitePDF, ImageKodec, AudioKodec, KiteQR.