データの圧縮と展開
Posted feedbacks - Scala
java.util.zipパッケージを使って書いてみました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | import java.io.{File, BufferedInputStream, BufferedOutputStream, FileInputStream, FileOutputStream, InputStream, OutputStream}
import java.util.zip.{ZipEntry, ZipInputStream, ZipOutputStream}
import scala.collection.mutable.HashSet
object Zip {
def compress(s:String, d:String):Unit =
(new File(s)) match {
case f if !f.exists => throw new IllegalArgumentException("no such file.")
case f => {
val o:ZipOutputStream = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(d)))
val c:HashSet[File] = new HashSet
val b:Array[Byte] = new Array(2048)
def output(i:InputStream):Unit = i.read(b) match {
case -1 => i.close
case l => {
o.write(b, 0, l)
output(i)
}
}
def addEntry(p:String, w:Option[(InputStream)=>Unit]):Unit = {
o.putNextEntry(new ZipEntry(p))
if (w != None) (w.get)(new BufferedInputStream(new FileInputStream(p)))
o.closeEntry
}
def addDirectory(f:File):Unit =
if (f != null) {
addDirectory(f.getParentFile)
if (!c.contains(f)) {
c += f
addEntry(f.getPath.replaceAll("\\\\", "/").replaceFirst("/?$", "/"), None)
}
}
def loop(f:File):Unit =
if (f.isFile)
addEntry(f.getPath.replaceAll("\\\\", "/"), Some(output _))
else {
addDirectory(f)
f.listFiles.foreach(loop _)
}
if (f.isFile) addDirectory(f.getParentFile)
loop(f)
o.close
}
}
def decompress(s:String):Unit =
(new File(s)) match {
case f if !f.exists => throw new IllegalArgumentException("no such file.")
case f => {
val i:ZipInputStream = new ZipInputStream(new BufferedInputStream(new FileInputStream(f)))
val b:Array[Byte] = new Array(2048)
def output(o:OutputStream):Unit = i.read(b) match {
case -1 => o.close
case l => {
o.write(b, 0, l)
output(o)
}
}
def loop:Unit = {
val e:ZipEntry = i.getNextEntry
if (e == null)
i.close
else {
if (e.isDirectory)
(new File(e.getName)).mkdirs
else {
val f:File = new File(e.getName)
if (f.getParentFile != null && !f.exists) f.getParentFile.mkdirs
output(new BufferedOutputStream(new FileOutputStream(f)))
}
i.closeEntry
loop
}
}
loop
}
}
}
object Compress {
import Zip._
def main(args:Array[String]):Unit =
try {
args.size match {
case 2 => args.first match {
case "-d" => decompress(args.last)
case _ => compress(args.first, args.last)
}
case _ => throw new IllegalArgumentException("invalid option.")
}
} catch {
case e:IllegalArgumentException => println("usage: Compress {-d SOURCE | SOURCE DSTINATION}")
case e => e.printStackTrace
}
}
|

mattsan
#8262()
Rating1/5=0.20
データを圧縮するcompress、展開するdecompressという関数やメソッドなどを書いてください。データはバイト列でもストリームでもそれ以外の形式でもOKです。
圧縮形式は問いませんが、できるだけ一般的なフォーマット(zip,lzhなど)でお願いします。
また、標準以外のライブラリを使う場合には出典の記載をお願いします。
「○○でも実用的な圧縮/展開プログラムがかけるんだぞ!」というのを、ぜひ示してください。
[ reply ]