Я обнаружил, что разархивировать содержимое файла на удивление сложно в Clojure или Java, потому что вы должны сами создать структуру каталогов. Я могу представить, что есть готовые библиотеки, но я однажды использовал что-то вроде следующего:
;; in project.clj or build.boot add dependency
;; [org.apache.commons/commons-compress "1.3"]
(ns com.example.my.namespace
(:require
[clojure.java.io :as io]
[clojure.tools.logging :as log])
(:import
[org.apache.commons.compress.archivers.zip ZipFile ZipArchiveEntry]))
;; Note that make-parents is called for every file. Tested with ZIP
;; with ca 80k files. Not significantly slower than testing here for
;; .isDirectory and only then create the parents. Keeping the nicer
;; code with this comment, then.
(defn- unzip-file [zip-file to-dir]
(log/infof "Extracting %s" zip-file)
(log/debug " to:" to-dir)
(with-open [zipf (ZipFile. (io/file zip-file))]
(doseq [entry (enumeration-seq (.getEntries zipf))
:when (not (.isDirectory ^ZipArchiveEntry entry))
:let [zip-in-s (.getInputStream zipf entry)
out-file (io/file (str to-dir
java.io.File/separator
(.getName entry)))]]
(log/trace " ->" (.getName out-file))
(io/make-parents out-file)
(with-open [entry-o-s (io/output-stream out-file)]
(io/copy zip-in-s entry-o-s)))))
Повторные вызовы io/make-parents
не имели значения в моих тестах.
Я не уверен, действительно ли это то, что вы хотите использовать. Просто чтение одного файла из Zip, вероятно, будет сделано без извлечения всего остального. Я все же перебираю содержимое zip-файла таким же образом. Только не создавайте выходную структуру и вместо использования io/copy
для потоковой передачи содержимого из zip-файла в другой файл на dis c slurp
из входного потока.