clojurezip

Zip a file in clojure


I want to zip a file in clojure and I can't find any libraries to do it.

Do you know a good way to zip a file or a folder in Clojure? Must I use a java library?


Solution

  • There is a stock ZipOutputStream in Java which can be used from Clojure. I don't know whether there is a library somewhere. I use the plain Java functions with a small helper macro:

    (defmacro ^:private with-entry
      [zip entry-name & body]
      `(let [^ZipOutputStream zip# ~zip]
         (.putNextEntry zip# (ZipEntry. ~entry-name))
         ~@body
         (flush)
         (.closeEntry zip#)))
    

    Obviously every ZIP entry describes a file.

    (require '[clojure.java.io :as io])
    
    (with-open [file (io/output-stream "foo.zip")
                zip  (ZipOutputStream. file)
                wrt  (io/writer zip)]
      (binding [*out* wrt]
        (doto zip
          (with-entry "foo.txt"
            (println "foo"))
          (with-entry "bar/baz.txt"
            (println "baz")))))
    

    To zip a file you might want to do something like this:

    (with-open [output (ZipOutputStream. (io/output-stream "foo.zip"))
                input  (io/input-stream "foo")]
      (with-entry output "foo"
        (io/copy input output)))