Zip a file in clojure
Asked Answered
F

5

8

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?

Forster answered 31/7, 2013 at 8:52 Comment(3)
Just curious, why do you not want to use a Java library? Using existing java libs is one of the biggest USPs of clojure and other JVM based languages. Why reinvent the wheel?Roily
I thought use an existing library... I don't understand your answer. Maybe my english is bad... What is USP ?Forster
@Forster USP = Unique selling propositionSeto
C
19

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)))
Circumfluent answered 31/7, 2013 at 9:24 Comment(3)
Thanks ! And the import for ZipOutputStream is : (:import [java.util.zip ZipOutputStream]).Forster
Or just (:import java.util.zip.ZipOutputStream).Circumfluent
Yes... Because I forgot ZipEntry : (:import [java.util.zip ZipEntry ZipOutputStream])Forster
T
3

All compression and decompression of files can be done with a simple shell command which we can access through clojure.java.shell

Using the same method you can also compress and decompress any compression type you would usually from your terminal.

(use '[clojure.java.shell :only [sh]])


(defn unpack-resources [in out]
  (clojure.java.shell/sh 
   "sh" "-c" 
  (str " unzip " in " -d " out)))

(defn pack-resources [in out]
  (clojure.java.shell/sh 
   "sh" "-c" 
  (str " zip " in " -r " out)))

(unpack-resources "/path/to/my/zip/foo.zip" 
                  "/path/to/store/unzipped/files")

(pack-resources "/path/to/store/archive/myZipArchiveName.zip" 
                "/path/to/my/file/myTextFile.csv")
Tedder answered 1/9, 2015 at 20:48 Comment(1)
When using files that are Java objects and look like: #object[java.io.File 0x4d541cba "/tmp/7bbfdfaf-8b00-4bdc-b7c2-bc270d6564b4.zip"], the str changes them into a mere string with only "/tmp/7bbfdfaf-8b00-4bdc-b7c2-bc270d6564b4.zip" in it, and the function fails with file not found error. What would you suggest for a case like this?Sulphurbottom
C
0

You can import this (gzip) https://gist.github.com/bpsm/1858654 Its quite interesting. Or more precisely, you can use this

(defn gzip    
[input output & opts]
(with-open [output (-> output clojure.java.io/output-stream GZIPOutputStream.)]
 (with-open [rdr (clojure.java.io/reader input)]
  (doall (apply clojure.java.io/copy rdr output opts)))))
Champion answered 27/2, 2016 at 21:24 Comment(0)
N
0

You can use rtcritical/clj-ant-tasks library that wraps Apache Ant, and zip with a single command.

Add library dependency [rtcritical/clj-ant-tasks "1.0.1"]

(require '[rtcritical.clj-ant-tasks :refer [run-ant-task]])

To zip a file:

(run-ant-task :zip {:destfile "/tmp/file-zipped.zip" 
                    :basedir "/tmp"
                    :includes "file-to-zip"})

Note: run-ant-task(s) functions in this library namespace can be used to run any other Apache Ant task(s) as well.

For more information, see https://github.com/rtcritical/clj-ant-tasks

Ninfaningal answered 27/1, 2020 at 16:1 Comment(0)
S
0

There's a library for handling (compressed) archives brewing over here: https://github.com/luposlip/clarch

Supranatural answered 11/6 at 14:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.