2017-09-29 27 views
1

我有一个文件夹结构是这样的:资源Clojure的子文件夹列表中uberjar

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

我已经建立了我运行的罐子lein uberjar

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

我知道我可以使用clojure.java.io

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

获得资源/ A/B/x.txt的内容,但我无法找到一个简单的方法来列出子文件夹。

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

有没有图书馆这样做?

+0

的[我如何列出一个JAR文件里的文件可能的复制?](https://stackoverflow.com/questions/1429172/how-do-i-list-the-files-inside-a-jar-file) – leetwinski

+0

这些都没有显示1)一个简单的方法来做到这一点2)这是一个图书馆。我拒绝接受这个答案是一大堆java代码。 – siltalau

+0

好..它是一种简单的任务,将java代码翻译成clojure。 – leetwinski

回答

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/"))))) 

被投入到主命名空间,并与罐子运行将输出在/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) #".*"))))) 
+0

我接受这个作为正确的答案 - 它在技术上是。解决方案的复杂性告诉我,我试图完全错误的做法。 – siltalau

0

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

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

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