Skip to content

gonearewe/SevenZ4S

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

19 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

SevenZ4S

Maven Central Scaladoc GitHub stars GitHub forks GitHub issues license

Introduction

This a 7Z compression library for Scala(v2.13), providing simple api to create, update and extract archives of different formats.

This library offers compression and update abilities for 5 formats:

7-Zip	Zip	 GZip	Tar	 BZip2

As for extraction, following formats are all supported:

7-Zip	Zip	Rar	Tar	 Split	Lzma   Iso	HFS	 GZip
Cpio	BZip2	Z	 Arj	Chm	   Lhz	Cab	 Nsis
Ar/A/Lib/Deb	Rpm	 Wim	Udf	   Fat	Ntfs

Multiple platforms are also supported.

This project is based on net.sf.sevenzipjbinding, which is a 7z binding library for java. You may acquire more info from its homepage. Also, it's licensed under LGPL and unRAR restriction.

Quick Start

For creating archives, you need to first acquire an instance of concrete ArchiveCreator. There're 5 kinds of ArchiveCreator, one for each format. Some features and callback hooks may be optional. Archive is composed of many entries, you need to pass some to compress method to finish compression. Object SevenZ4S provides some utils that may help gain entries from local file system.

  val path: Path = new File(getClass.getResource("/root").getFile).toPath

  def create7Z(): Unit = {
    val entries = SevenZ4S.get7ZEntriesFrom(path)
    new ArchiveCreator7Z()
      .towards(path.resolveSibling("root.7z"))
      // archive-relevant features
      .setLevel(5)
      .setSolid(true)
      .setHeaderEncryption(true)
      .setPassword("12345")
      .setThreadCount(3)
      .onEachEnd {
        ok =>
          if (ok)
            println("one success")
          else
            println("one failure")
      }.onProcess {
      (completed, total) =>
        println(s"$completed of $total")
    }.compress(entries)
  }

7Z engine offers abilities to modify, append and remove a few entries in a more efficient way. Use ArchiveUpdater to update archive instead of extract-modify-compress by yourself.

  // import ...
  import fun.mactavish.sevenz4s.Implicits._
  
  def update7Z(): Unit = {
    val replacement = path.resolveSibling("replace.txt")

    val updater = new ArchiveUpdater7Z()
      .from(path.resolveSibling("root.7z")) // update itself
      .withPassword("12345")
      .update {
        entry =>
          if (entry.path == "root\\a.txt") { // path separator is OS-relevant
            entry.copy(
              dataSize = Files.size(replacement), // remember to update size
              source = replacement, // implicit conversion happens here
              path = "root\\a replaced.txt" // file name contains space
            )
          } else {
            entry
          }
      }

    updater.removeWhere(entry => entry.path == "root\\sub\\deeper\\c.txt")
    // directory can not be deleted until its contents have all been deleted,
    // otherwise, it ignores the request silently rather than raise an exception.
    updater.removeWhere(entry => entry.path == "root\\sub\\deeper")
    updater += SevenZ4S.get7ZEntriesFrom(replacement).head
    // notice that file with the same name is allowed,
    // but may be overwritten by OS's file system during extraction
    updater += SevenZ4S.get7ZEntriesFrom(replacement).head
  }

Unlike ArchiveCreator and ArchiveUpdater, SevenZ4S provides a generic ArchiveExtractor supporting the extraction of all formats. It can autodetect the format of input archive.

  def extract7Z(): Unit = {
    new ArchiveExtractor()
      .from(path.resolveSibling("root.7z"))
      .withPassword("12345")
      .onEachEnd(println(_))
      .foreach { entry =>
        println(entry.path)
        if (entry.path == "root\\b.txt") {
          // extract independently
          entry.extractTo(path.resolveSibling("b extraction.txt"))
        }
      }
      // `extractTo` takes output folder `Path` as parameter
      // `onEachEnd` callback only triggers on `extractTo`
      .extractTo(path.resolveSibling("extraction"))
      .close() // ArchiveExtractor requires closing
  }

If all you want is simply compressing and extracting files on local file system, the object SevenZ4S provides super useful utilities.

  val path: Path = new File(getClass.getResource("/root").getFile).toPath

  def test7Z(): Unit = {
    val output = path.resolveSibling("util test/7z")

    SevenZ4S.compress(ArchiveFormat.SEVEN_Z, path, output)
    val f = output.resolve("root.7z")

    SevenZ4S.extract(f, output)
  }

Refer to the test cases and test resources for more details.