Kotlinでファイルを圧縮/展開する

KotlinでファイルをZip圧縮/展開するコードを実装したので。

ちなみにディスク容量のセーフティとかはかけていません。

ファイルを圧縮する

ファイルをZIPに圧縮するには ZipOutputStreamを使用します。

// 指定したファイル/ディレクトリをZip圧縮する
// ファイルはZipのルートに、ディレクトリは構造を維持して格納される
fun archive(sources: List<File>, target: File): Unit {
    ZipOutputStream(target.outputStream()).use { zos ->
        sources.forEach { source->
            if(source.isDirectory.not()){
                // ファイルならばそのままルートにデータを流し込む
                zos.putNextEntry(ZipEntry(source.name))
                source.inputStream().copyTo(zos, 256)
            }else{
                // ディレクトリなら走査する
                source.walk()
                    .filterNot { it.isHidden } // 隠しファイルは除外
                    .forEach {file->
                        if (file.isDirectory) {
                            // ディレクトリだった場合、Zipの中にディレクトリを切る
                            zos.putNextEntry(ZipEntry("${file.relativeTo(source)}/"))
                            zos.closeEntry()
                        } else {
                            // ファイルだった場合、データを流し込む
                            zos.putNextEntry(ZipEntry(file.relativeTo(source).toString()))
                            file.inputStream().copyTo(zos, 256)
                        }
                    }
            }
        }
    }
}

ファイルを展開する

Zipファイルを展開するにはZipInputStreamを使用します。

// ファイル展開する際に次のEntryを見ながらループを回すのに代入ループ(伝われ)が出来ないので拡張
fun ZipInputStream.forEach(R: (ZipEntry)->Unit){
    var entry = nextEntry
    while (entry != null){
        R(entry)
        entry = nextEntry
    }
}

// 指定したZipファイルを任意の場所に展開する
fun extract(source: Path, target: Path){
    ZipInputStream(Files.newInputStream(source)).use { zis->
        zis.forEach {entry->
            val dst = File(target.toFile(), entry.name)
            if(entry.isDirectory){
                // エントリーがディレクトリならディレクトリ作成する
                dst.mkdirs()
            }else{
                // エントリーがファイルなら念の為にフォルダを切った後にデータを吸い出す
                dst.parentFile?.mkdirs()
                zis.copyTo(BufferedOutputStream(FileOutputStream(dst)))
            }
        }
    }
}
© 2019 - 2023 ここあ