Skip to content

Commit

Permalink
Integrate Zipper to ScZip
Browse files Browse the repository at this point in the history
  • Loading branch information
yuchesc committed Aug 1, 2018
1 parent 33dfa91 commit 14c4594
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 105 deletions.
102 changes: 97 additions & 5 deletions src/main/scala/com/yuchesc/sczip/ScZip.scala
Original file line number Diff line number Diff line change
@@ -1,15 +1,107 @@
package com.yuchesc.sczip

import java.io._
import java.nio.file._
import java.io.{BufferedInputStream, OutputStream, _}
import java.nio.file.attribute.BasicFileAttributes
import java.nio.file.{FileVisitResult, Files, Path, SimpleFileVisitor, _}
import java.util.zip.{ZipEntry, ZipOutputStream}

import com.yuchesc.sczip.lib._
import com.yuchesc.sczip.lib.{Condition, _}

import scala.collection.mutable.ListBuffer

/**
* Zip executor.
*
* @param out the output stream
* @param normalizeRootPath if true, eliminate root or relative path from starting point. (Default: true)
* @param capacity file reading buffer size. (Default: 4096)
*/
class ScZip(out: OutputStream,
val normalizeRootPath: Boolean = true,
val capacity: Int = 4096) {

private val zip: ZipOutputStream = new ZipOutputStream(out)
private val buffer: Array[Byte] = Array.ofDim[Byte](capacity)

protected def getEntryName(file: Path): String = if (normalizeRootPath) {
file.toString dropWhile ("./\\" contains _)
} else {
file.toString
}

/**
* Add a file to zip.
*
* @param path Target file
* @return added entry name
*/
def add(path: Path): String = {
val entryName = getEntryName(path)
val entry = new ZipEntry(entryName)
entry.setTime(Files.getLastModifiedTime(path).toMillis)
zip.putNextEntry(entry)
var in = None: Option[BufferedInputStream]
try {
in = Option(new BufferedInputStream(Files.newInputStream(path)))
Stream.continually(in.get.read(buffer))
.takeWhile(_ != -1)
.foreach(zip.write(buffer, 0, _))
zip.closeEntry()
entryName
} finally {
in.foreach(_.close())
}
}

/**
* Add a file to zip.
*
* @param root Target file path
* @param exclude Exclude files from target via glob match pattern.
* @return added entry name list
*/
def addTree(root: Path, exclude: Option[Condition] = None): Seq[String] = {
val list = ListBuffer.empty[String]
Files.walkFileTree(root, new SimpleFileVisitor[Path] {
override def visitFile(file: Path, attrs: BasicFileAttributes): FileVisitResult = {
if (exclude.isEmpty || !exclude.get.hit(file)) {
list.append(add(file))
}
FileVisitResult.CONTINUE
}
})
list
}

/**
* Close zip stream.
*/
def close(): Unit = zip.close()
}

/**
* Make zip easily.
*/
object ScZip {

/**
* Use zipper object with auto close.
*
* @param out the output stream
* @param f implement
* @tparam A return type
* @return
*/
def withResource[A](out: OutputStream, f: ScZip => A): A = {
var zip: Option[ScZip] = None
try {
zip = Option(new ScZip(out))
f(zip.get)
} finally {
zip.foreach(_.close())
}
}

/**
* Make exclude object covered with Option.
*
Expand Down Expand Up @@ -51,7 +143,7 @@ object ScZip {
* @return entry name list
*/
def zipTree(targetPath: Path, out: OutputStream, exclude: Option[Condition] = None): Seq[String] = {
Zipper.withResource(out, {
ScZip.withResource(out, {
zip =>
zip.addTree(targetPath, exclude)
})
Expand Down Expand Up @@ -89,7 +181,7 @@ object ScZip {
* @return entry name list
*/
def zipFiles(files: Seq[Path], out: OutputStream): Seq[String] = {
Zipper.withResource(out, {
ScZip.withResource(out, {
zip =>
files.map(zip.add)
})
Expand Down
100 changes: 0 additions & 100 deletions src/main/scala/com/yuchesc/sczip/Zipper.scala

This file was deleted.

0 comments on commit 14c4594

Please sign in to comment.