我有一个像这样的文件夹结构:
我用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文件中的资源。
有没有这样做的图书馆?
答案 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")))