codememo

scala를 사용하여 zip 파일을 압축 해제하려면 어떻게 해야 합니까?

tipmemo 2023. 4. 23. 10:29
반응형

scala를 사용하여 zip 파일을 압축 해제하려면 어떻게 해야 합니까?

기본적으로는 modeled라는 폴더가 포함된 .zip 파일의 압축을 풀어야 합니다.이 폴더에는 다수의 Excel 파일이 포함되어 있습니다.

Zip 파일을 압축 해제하기 위한 코드(ZipArchive)가 이미 쓰여져 있는 것을 발견했지만, 사용 시에 에러 메세지가 표시되는 이유를 알 수 없습니다.ZipArchive 코드와 오류 메시지는 다음과 같습니다.

import java.io.{OutputStream, InputStream, File, FileOutputStream}
import java.util.zip.{ZipEntry, ZipFile}
import scala.collection.JavaConversions._

object ZipArchive {

  val BUFSIZE = 4096
  val buffer = new Array[Byte](BUFSIZE)

  def unZip(source: String, targetFolder: String) = {
    val zipFile = new ZipFile(source)

    unzipAllFile(zipFile.entries.toList, getZipEntryInputStream(zipFile)_, new File(targetFolder))
  }

  def getZipEntryInputStream(zipFile: ZipFile)(entry: ZipEntry) = zipFile.getInputStream(entry)

  def unzipAllFile(entryList: List[ZipEntry], inputGetter: (ZipEntry) => InputStream, targetFolder: File): Boolean = {

    entryList match {
      case entry :: entries =>

        if (entry.isDirectory)
          new File(targetFolder, entry.getName).mkdirs
        else
          saveFile(inputGetter(entry), new FileOutputStream(new File(targetFolder, entry.getName)))

        unzipAllFile(entries, inputGetter, targetFolder)
      case _ =>
        true
    }
  }

  def saveFile(fis: InputStream, fos: OutputStream) = {
    writeToFile(bufferReader(fis)_, fos)
    fis.close
    fos.close
  }

  def bufferReader(fis: InputStream)(buffer: Array[Byte]) = (fis.read(buffer), buffer)

  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
  }
}

오류 메시지:

java.io.FileNotFoundException: src/test/resources/oepTemp/modeled/EQ_US_2_NULL_('CA')_ALL_ELT_IL_EQ_US.xlsx (No such file or directory), took 6.406 sec
[error]     at java.io.FileOutputStream.open(Native Method)
[error]     at java.io.FileOutputStream.<init>(FileOutputStream.java:221)
[error]     at java.io.FileOutputStream.<init>(FileOutputStream.java:171)
[error]     at com.contract.testing.ZipArchive$.unzipAllFile(ZipArchive.scala:28)
[error]     at com.contract.testing.ZipArchive$.unZip(ZipArchive.scala:15)
[error]     at com.contract.testing.OepStepDefinitions$$anonfun$1.apply$mcZ$sp(OepStepDefinitions.scala:175)
[error]     at com.contract.testing.OepStepDefinitions$$anonfun$1.apply(OepStepDefinitions.scala:150)
[error]     at com.contract.testing.OepStepDefinitions$$anonfun$1.apply(OepStepDefinitions.scala:150)
[error]     at cucumber.api.scala.ScalaDsl$StepBody$$anonfun$apply$1.applyOrElse(ScalaDsl.scala:61)
[error]     at cucumber.api.scala.ScalaDsl$StepBody$$anonfun$apply$1.applyOrElse(ScalaDsl.scala:61)
[error]     at scala.runtime.AbstractPartialFunction.apply(AbstractPartialFunction.scala:36)
[error]     at cucumber.runtime.scala.ScalaStepDefinition.execute(ScalaStepDefinition.scala:71)
[error]     at cucumber.runtime.StepDefinitionMatch.runStep(StepDefinitionMatch.java:37)
[error]     at cucumber.runtime.Runtime.runStep(Runtime.java:298)
[error]     at cucumber.runtime.model.StepContainer.runStep(StepContainer.java:44)
[error]     at cucumber.runtime.model.StepContainer.runSteps(StepContainer.java:39)
[error]     at cucumber.runtime.model.CucumberScenario.run(CucumberScenario.java:48)
[error]     at cucumber.runtime.junit.ExecutionUnitRunner.run(ExecutionUnitRunner.java:91)
[error]     at cucumber.runtime.junit.FeatureRunner.runChild(FeatureRunner.java:63)
[error]     at cucumber.runtime.junit.FeatureRunner.runChild(FeatureRunner.java:18)
[error]     ...

에러 메세지에 근거해, export 한 Excel 파일을 검색하려고 하고 있는 것 같습니다.이 부분은 나를 완전히 흥분시킨다.어떤 도움이라도 주시면 감사하겠습니다.아래에 메서드라고 부르는 방법을 추가했습니다. 아마도 제가 바보 같은 일을 하고 있는 것 같습니다.또한 zip 파일을 추출할 수 있는 다른 방법을 사용하는 것도 찬성합니다.

val tempDirectoryDir = "src/test/resources/oepTemp/"
ZipArchive.unZip(tempDirectoryDir + "Sub Region Input - Output.zip", tempDirectoryDir)

이를 위해 보다 기능적이고 정확한 방법이 있습니다.

import java.io.{FileInputStream, FileOutputStream}
import java.util.zip.ZipInputStream
val fis = new FileInputStream("htl.zip")
val zis = new ZipInputStream(fis)
Stream.continually(zis.getNextEntry).takeWhile(_ != null).foreach{ file =>
    val fout = new FileOutputStream(file.getName)
    val buffer = new Array[Byte](1024)
    Stream.continually(zis.read(buffer)).takeWhile(_ != -1).foreach(fout.write(buffer, 0, _))
}

Tian-Liang의 솔루션을 사용해보니 디렉토리 구조의 zips에서는 동작하지 않는다는 것을 깨달았습니다.그래서 저는 이렇게 했습니다.

  import java.io.{FileOutputStream, InputStream}
  import java.nio.file.Path
  import java.util.zip.ZipInputStream

  def unzip(zipFile: InputStream, destination: Path): Unit = {
    val zis = new ZipInputStream(zipFile)

    Stream.continually(zis.getNextEntry).takeWhile(_ != null).foreach { file =>
      if (!file.isDirectory) {
        val outPath = destination.resolve(file.getName)
        val outPathParent = outPath.getParent
        if (!outPathParent.toFile.exists()) {
          outPathParent.toFile.mkdirs()
        }

        val outFile = outPath.toFile
        val out = new FileOutputStream(outFile)
        val buffer = new Array[Byte](4096)
        Stream.continually(zis.read(buffer)).takeWhile(_ != -1).foreach(out.write(buffer, 0, _))
      }
    }
  }

java에서 유틸리티를 사용했기 때문에 scala로 변환된 버전입니다.이것이 더 기능적일지도 모르지만 도움이 됩니다.

package zip

import java.io.{ IOException, FileOutputStream, FileInputStream, File }
import java.util.zip.{ ZipEntry, ZipInputStream }

/**
 * Created by anquegi on 04/06/15.
 */
object Unzip extends App {

  val INPUT_ZIP_FILE: String = "src/main/resources/my-zip.zip";
  val OUTPUT_FOLDER: String = "src/main/resources/my-zip";

  def unZipIt(zipFile: String, outputFolder: String): Unit = {

    val buffer = new Array[Byte](1024)

    try {

      //output directory
      val folder = new File(OUTPUT_FOLDER);
      if (!folder.exists()) {
        folder.mkdir();
      }

      //zip file content
      val zis: ZipInputStream = new ZipInputStream(new FileInputStream(zipFile));
      //get the zipped file list entry
      var ze: ZipEntry = zis.getNextEntry();

      while (ze != null) {

        val fileName = ze.getName();
        val newFile = new File(outputFolder + File.separator + fileName);

        System.out.println("file unzip : " + newFile.getAbsoluteFile());

        //create folders
        new File(newFile.getParent()).mkdirs();

        val fos = new FileOutputStream(newFile);

        var len: Int = zis.read(buffer);

        while (len > 0) {

          fos.write(buffer, 0, len)
          len = zis.read(buffer)
        }

        fos.close()
        ze = zis.getNextEntry()
      }

      zis.closeEntry()
      zis.close()

    } catch {
      case e: IOException => println("exception caught: " + e.getMessage)
    }

  }

  Unzip.unZipIt(INPUT_ZIP_FILE, OUTPUT_FOLDER)

}

경기 시작은 늦었지만, 이 기회를 이용해서scala.collection.JavaConverterszip 파일엔트리에 for-loop을 가져오고java.nio.Files간단한 복사 및 디렉토리 작성을 얻으려면:

import java.nio.file.{Files, Path}
import java.util.zip.ZipFile
import scala.collection.JavaConverters._

def unzip(zipPath: Path, outputPath: Path): Unit = {
  val zipFile = new ZipFile(zipPath.toFile)
  for (entry <- zipFile.entries.asScala) {
    val path = outputPath.resolve(entry.getName)
    if (entry.isDirectory) {
      Files.createDirectories(path)
    } else {
      Files.createDirectories(path.getParent)
      Files.copy(zipFile.getInputStream(entry), path)
    }
  }
}
import java.io.FileInputStream
import java.io.InputStream
import java.util.zip.ZipEntry
import java.util.zip.ZipInputStream
import scala.language.reflectiveCalls
import scala.util.Try

import org.apache.commons.io.IOUtils

def using[T <: { def close() }, U](resource: T)(block: T => U): U = {
  try {
    block(resource)
  } finally {
    if (resource != null) {
        resource.close()
    }
  }
}

def processZipFile(zipFile: ZipFile)(doStuff: ZipEntry => Unit) {
  using(new ZipInputStream(new FileInputStream(zipFile))) { zipInputStream =>
    val entries = Stream.continually(Try(zipInputStream.getNextEntry()).getOrElse(null))
        .takeWhile(_ != null) // while not EOF and not corrupted
        .foreach(doStuff)
        .force
  }
}

ZipFile.close()의 자동 호출을 Steve의 응답에 통합합니다.그것은 노엘 옙의 답변에 있는 사용법으로 만들어졌다.

import java.nio.file.{Files, Path}
import java.util.zip.ZipFile
import scala.collection.JavaConverters._

def using[T <: {def close()}, U](resource: T)(block: T => U): U = {
  try {
    block(resource)
  } finally {
    if (resource != null) {
      resource.close()
    }
  }
}

def unzip(zipPath: Path, outputPath: Path): Unit = {
  using(new ZipFile(zipPath.toFile)) { zipFile =>
    for (entry <- zipFile.entries.asScala) {
      val path = outputPath.resolve(entry.getName)
      if (entry.isDirectory) {
        Files.createDirectories(path)
      } else {
        Files.createDirectories(path.getParent)
        Files.copy(zipFile.getInputStream(entry), path)
      }
    }
  }
}

언급URL : https://stackoverflow.com/questions/30640627/how-to-unzip-a-zip-file-using-scala

반응형