如何使用clojure.java.io从特定的.jar文件加载资源

时间:2012-10-17 03:43:19

标签: clojure

clojure.java.io中,有一个io/resource函数,但我认为它只是加载正在运行的当前jar的资源。有没有办法指定资源所在的.jar文件?

例如:

  • 我有一个jar文件:/path/to/abc.jar
  • abc.jar解压缩时在解压缩目录的根目录中包含some/text/output.txt
  • output.txt包含字符串"The required text that I want."

我需要可以执行这些操作的函数:

(list-jar "/path/to/abc.jar" "some/text/")
;; => "output.txt"

(read-from-jar "/path/to/abc.jar" "some/text/output.txt")
;; => "The required text that I want"

提前致谢!

1 个答案:

答案 0 :(得分:2)

根据Ankur的评论,我设法拼凑了我需要的功能:

java.util.jar.JarFile对象完成工作。

您可以调用方法(.entries (Jarfile. a-path))来提供文件列表,但不是返回树结构:

即:

/dir-1
  /file-1
  /file-2
  /dir-2
    /file-3
  /dir-3
    /file-4

它返回文件名的枚举:

/dir-1/file-1, /dir-1/file-2, /dir-1/dir-2/file-3, /dir-1/dir-3/file-4

我需要的以下功能定义如下:

(import java.util.jar.JarFile)
(defn list-jar [jar-path inner-dir]
  (if-let [jar          (JarFile. jar-path)]
    (let [inner-dir    (if (and (not= "" inner-dir) (not= "/" (last inner-dir)))
                         (str inner-dir "/")
                         inner-dir)
          entries      (enumeration-seq (.entries jar))
          names        (map (fn [x] (.getName x)) entries)
          snames       (filter (fn [x] (= 0 (.indexOf x inner-dir))) names)
          fsnames      (map #(subs % (count inner-dir)) snames)]
      fsnames)))

(defn read-from-jar [jar-path inner-path]
  (if-let [jar   (JarFile. jar-path)]
    (if-let [entry (.getJarEntry jar inner-path)]
      (slurp (.getInputStream jar entry)))))

用法:


(read-from-jar "/Users/Chris/.m2/repository/lein-newnew/lein-newnew/0.3.5/lein-newnew-0.3.5.jar"
               "leiningen/new.clj")

;=> "The list of built-in templates can be shown with `lein help new`....."

(list-jar  "/Users/Chris/.m2/repository/lein-newnew/lein-newnew/0.3.5/lein-newnew-0.3.5.jar" "leiningen")
;; => (new/app/core.clj new/app/project.clj .....)