clojure: unzipping a zip file stored as a resource

clojure, jar, zip

Solution

You can simply read from the `ZipInputStream` after you got the next entry. Use the size information from the entry to read the content.

user=> (import 'java.util.zip.ZipInputStream)
java.util.zip.ZipInputStream
user=> (def zs (ZipInputStream. (io/input-stream "foo.zip")))
#'user/zs
user=> (def ze (.getNextEntry zs))
#'user/ze
user=> (.getName ze)
"foo.txt"
user=> (.getSize ze)
21
user=> (let [bytes (byte-array 21)] (.read zs bytes 0 21) (String. bytes "UTF-8"))
"Das ist ein Test!\r\n\r\n"

Problem

I have been struggling with reading out the contents of a resources directory in my lein project. I understand now (after doing it wrong for awhile) to use clojure.java.io/resource to pull out a resource, because just using the file system doesn't work when it is packaged as a jar: ``` > (require '[clojure.java.io :as io]) > (def zipzip (.openStream (io/resource "zip.zip"))) ``` This returns a `BufferedInputStream`. What I want to do is take this zip file and unpack it to a local directory. I can't make a `ZipFile` out of it, but I can make a `ZipInputStream`. Unfortunately, while I can get `ZipEntries` out of this, I need a `ZipFile` to actually read the contents of the `ZipEntry`. I can do this: ``` > (-> zipzip ZipInputStream. .getNextEntry .getName) ``` This returns the name, but there is nothing in the api docs to get the actual contents of that `ZipEntry` with the `ZipInputStream`! How do I write out the contents from this `ZipInputStream` to a local directory? (that also works when the code is packaged into a jar!)

Original source