Compression and archives with zio-streams
ZIO Streams Compress integrates several compression algorithms and archive formats with ZIO Streams.
We are open for comments
Please open an issue or contact us on Discord if you have suggestions. The API will stabilize in Jan 2025, followed by a 1.0.0 release.
Installation
In order to use this library, we need to add one of the following line in our build.sbt
file:
libraryDependencies += "dev.zio" %% "zio-streams-compress-brotli" % "0.0.2"
libraryDependencies += "dev.zio" %% "zio-streams-compress-brotli4j" % "0.0.2"
libraryDependencies += "dev.zio" %% "zio-streams-compress-bzip2" % "0.0.2"
libraryDependencies += "dev.zio" %% "zio-streams-compress-gzip" % "0.0.2"
libraryDependencies += "dev.zio" %% "zio-streams-compress-lz4" % "0.0.2"
libraryDependencies += "dev.zio" %% "zio-streams-compress-tar" % "0.0.2"
libraryDependencies += "dev.zio" %% "zio-streams-compress-zip" % "0.0.2"
libraryDependencies += "dev.zio" %% "zio-streams-compress-zip4j" % "0.0.2"
libraryDependencies += "dev.zio" %% "zio-streams-compress-zstd" % "0.0.2"
For Brotli you can choose between the 'brotli' and the 'brotli4j' version. The first is based on the official Java library but only does decompression. The second is based on Brotli4J which does compression and decompression.
For ZIP files you can choose between the 'zip' and the 'zip4j' version. The first allows you to tweak the compression level, while the second allows you work with password-protected ZIP files.
Currently only jvm is supported. PRs for scala-js and scala-native are welcome.
Example
// Example.sc
// Run with: scala-cli Example.sc
//> using dep dev.zio:zio-streams-compress-gzip:0.0.2
//> using dep dev.zio:zio-streams-compress-tar:0.0.2
//> using dep dev.zio:zio-streams-compress-zip4j:0.0.2
import zio._
import zio.compress.{ArchiveEntry, GzipCompressor, GzipDecompressor, TarUnarchiver, Zip4JArchiver}
import zio.stream._
import java.nio.charset.StandardCharsets.UTF_8
object ExampleApp extends ZIOAppDefault {
override def run: ZIO[Any, Any, Any] =
for {
// Compress a file with GZIP
_ <- ZStream
.fromFileName("file")
.via(GzipCompressor.compress)
.run(ZSink.fromFileName("file.gz"))
// List all items in a gzip tar archive:
_ <- ZStream
.fromFileName("file.tgz")
.via(GzipDecompressor.decompress)
.via(TarUnarchiver.unarchive)
.mapZIO { case (archiveEntry, contentStream) =>
for {
content <- contentStream.runCollect
_ <- Console.printLine(s"${archiveEntry.name} ${content.length}")
} yield ()
}
.runDrain
// Create an encrypted ZIP archive
_ <- ZStream(archiveEntry("file1.txt", "Hello world!".getBytes(UTF_8)))
.via(Zip4JArchiver(password = Some("it is a secret")).archive)
.run(ZSink.fromFileName("file.zip"))
} yield ()
private def archiveEntry(
name: String,
content: Array[Byte],
): (ArchiveEntry[Some, Any], ZStream[Any, Throwable, Byte]) =
(ArchiveEntry(name, Some(content.length.toLong)), ZStream.fromIterable(content))
}
Running the tests
SBT_OPTS="-Xmx4G -XX:+UseG1GC" sbt test