Clojure压缩目录为zip

创建zip压缩文件主要思想:

  1. 创建ZipOutputStream
  2. 创建ZipEntry,并调用putNextEntry
  3. copy文件到output stream
  4. 调用closeEntry关闭entry
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
(require '[clojure.java.io :as io]
'[clojure.string :as str])
(import (java.io FileOutputStream)
(java.util.zip ZipEntry ZipOutputStream))
(defn zip-dir
"以zip格式压缩目录path"
[path zip-file]
(let [root-path (.toPath (io/file path))]
(with-open [zip (ZipOutputStream. (FileOutputStream. zip-file))]
(doseq [f (file-seq (io/file path))]
(let [p (.toPath f)
subpath (str/replace (str (.relativize root-path p)) "\\" "/")
path-name (if (.isDirectory f) (str subpath "/") subpath)]
(when-not (= "" subpath)
(.putNextEntry zip (ZipEntry. path-name))
(when (.isFile f)
(io/copy f zip))
(.closeEntry zip)))))))

特别需要注意:

  1. 是在windows系统下,文件路径是以反斜杠(\)分割的,需要转换成斜杠(/)。(str/replace (str (.relativize root-path p)) "\\" "/")
  2. 如果是目录,entry需要以斜杠(/)结尾
  3. 如果是要压缩的根目录,需要忽略

ZipEntry的构造函数为:ZipEntry(String name),目录需要以/结尾