Skip to content

Instantly share code, notes, and snippets.

@Swind
Created May 5, 2012 09:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Swind/2601206 to your computer and use it in GitHub Desktop.
Save Swind/2601206 to your computer and use it in GitHub Desktop.
[Scala][Zip] This use apache common compress to unzip a zip file.
package tw.epubcoverter
import java.util.zip.ZipFile
import java.io.FileInputStream
import java.io.FileOutputStream
import scala.collection.JavaConversions._
import java.io.InputStream
import java.io.OutputStream
import java.io.File
import java.util.zip.ZipEntry
class ZipArchive {
val BUFSIZE = 4096
val buffer = new Array[Byte](BUFSIZE)
def unZip(source: String, targetFolder: String) = {
FileIsExist(source)
{
val zipFile = new ZipFile(source)
unzipAllFile(zipFile.entries.toList, getZipEntryInputStream(zipFile)_, new File(targetFolder))
}
}
def FileIsExist(path:String)(expr: => Any) = {
if(new File(path).exists)
expr
}
/*---------------------------------------------------------------------------------
* curry method , this methond can get the inputstream of a zip entry from zipFile
*---------------------------------------------------------------------------------*/
def getZipEntryInputStream(zipFile: ZipFile)(entry: ZipEntry) = zipFile.getInputStream(entry)
def unzipAllFile(entryList: List[ZipEntry], getInputStream: (ZipEntry) => InputStream, targetFolder: File): Boolean = {
entryList match {
case entry :: entries =>
if (entry.isDirectory)
new File(targetFolder, entry.getName).mkdirs
else
saveFile(getInputStream(entry), new FileOutputStream(new File(targetFolder, entry.getName)))
unzipAllFile(entries, getInputStream, targetFolder)
case _ =>
true
}
}
/*=============================================================
*
* Read InputStream and write the data to OutputStream
* the recursive method is writeToFile and bufferReader
*
*=============================================================*/
def saveFile(fis: InputStream, fos: OutputStream) = {
/*--------------------------------------------------------------
* curry a method , the method can read data from InputStream
*--------------------------------------------------------------*/
def bufferReader(fis: InputStream)(buffer: Array[Byte]) = (fis.read(buffer), buffer)
/*--------------------------------------------------------------
* Write the data in the buffer to outputstream
---------------------------------------------------------------*/
def writeToFile(reader: (Array[Byte]) => Tuple2[Int, Array[Byte]], fos: OutputStream): Boolean = {
val (length, data) = reader(buffer)
if (length >= 0) {
fos.write(data, 0, length)
writeToFile(reader, fos)
} else
true
}
try {
writeToFile(bufferReader(fis)_, fos)
} finally {
fis.close
fos.close
}
}
}
@tindzk
Copy link

tindzk commented Jun 12, 2018

You can shorten the code by using IOUtils.copy():

object ZipArchive {
  def unZip(source: File, targetFolder: File): Unit = {
    val zipFile = new ZipFile(source)
    try
      zipFile.entries.asScala.foreach { entry =>
        val target = new File(targetFolder, entry.getName)
        if (entry.isDirectory) target.mkdirs()
        else {
          target.getParentFile.mkdirs()
          val in  = zipFile.getInputStream(entry)
          val out = new FileOutputStream(target)
          IOUtils.copy(in, out)
          IOUtils.closeQuietly(in)
          out.close()
        }
      }
    finally zipFile.close()
  }
}

@balajiintech
Copy link

balajiintech commented Jan 8, 2020

im getting below error.

java.util.zip.ZipException: invalid END header (bad central directory offset)

-- Found solution.. zip file was ftp'd in ascii mode.. once i changed to binary mode.. it worked.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment