Clojure列出了uberjar资源中的子文件夹

时间:2017-09-29 12:05:02

标签: java file jar clojure

我有一个像这样的文件夹结构:

  • 资源
    • 一个
      • b
        • x.txt
      • Ç
        • x.txt

我用lein uberjar创建了我的可运行jar。

运行我的jar时,我想列出a的子文件夹。

我知道我可以使用clojure.java.io获取资源/ a / b / x.txt的内容

(slurp (clojure.java.io/resource "a/b/x.txt"))

但我找不到列出子文件夹的简单方法。

(clojure.java.io/file (clojure.java.io/resource "a"))只会生成java.lang.IllegalArgumentException: Not a file,因为它不是文件,而是jar文件中的资源。

有没有这样做的图书馆?

2 个答案:

答案 0 :(得分:2)

这是java特定答案的代码端口:

(ns my-project.core
  (:require [clojure.string :as cs])
  (:import java.util.zip.ZipInputStream)
  (:gen-class))

(defrecord HELPER [])

(defn get-code-location []
  (when-let [src (.getCodeSource (.getProtectionDomain HELPER))]
    (.getLocation src)))

(defn list-zip-contents [zip-location]
  (with-open [zip-stream (ZipInputStream. (.openStream zip-location))]
    (loop [dirs []]
      (if-let [entry (.getNextEntry zip-stream)]
        (recur (conj dirs (.getName entry)))
        dirs))))

(defn -main [& args]
  (println (some->> (get-code-location)
                    list-zip-contents
                    (filter #(cs/starts-with? % "a/")))))

放入主命名空间并使用jar运行将输出/resources/a文件夹中的所有路径..

java -jar ./target/my-project-0.1.0-SNAPSHOT-standalone.jar 
;;=> (a/ a/b/ a/b/222.txt a/222.txt)

另外一些快速的研究引导我进入这个库: https://github.com/ronmamo/reflections

它缩短了代码,但也需要项目的一些依赖项(我猜这可能是不可取的):

[org.reflections/reflections "0.9.11"]
[javax.servlet/servlet-api "2.5"]
[com.google.guava/guava "23.0"]

代码是这样的:

(ns my-project.core
  (:require [clojure.string :as cs])
  (:import java.util.zip.ZipInputStream
           [org.reflections
            Reflections
            scanners.ResourcesScanner
            scanners.Scanner
            util.ClasspathHelper
            util.ConfigurationBuilder])
  (:gen-class))

(defn -main [& args]
  (let [conf (doto (ConfigurationBuilder.)
               (.setScanners (into-array Scanner [(ResourcesScanner.)]))
               (.setUrls (ClasspathHelper/forClassLoader (make-array ClassLoader 0))))]
    (println
     (filter #(cs/starts-with? % "a/")
             (.getResources (Reflections. conf) #".*")))))

答案 1 :(得分:0)

另一种方法(但我必须承认它并不完全令人满意)是在编译时读取内容。假设您有一个函数list-files,它为您提供项目根目录中的列表:

(defmacro compile-time-filelist []
  `'~(list-files "resources/a"))

(defmacro compile-time-filelist []
  (vec (list-files "resources/a")))