2017-09-29 50 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")))