2017-09-29 2 views
1

Ich habe eine Ordnerstruktur wie folgt:Clojure Liste Unterordner in Ressourcen in uberjar

  • Ressourcen
    • ein
      • b
        • x.txt
      • c
        • x.txt

Ich habe meine runnable Glas mit lein uberjar erstellt.

Wenn ich mein jar ausführe, möchte ich die Unterordner von a auflisten.

Ich weiß, ich kann den Inhalt von Ressourcen/a/b/x.txt erhalten clojure.java.io mit

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

Aber ich kann nicht eine einfache Möglichkeit zur Liste der Unterordner finden.

(clojure.java.io/file (clojure.java.io/resource "a")) nur Ergebnisse in einer java.lang.IllegalArgumentException: Not a file, weil es keine Datei ist, ist es eine Ressource in der JAR-Datei.

Gibt es eine Bibliothek, die das tut?

+0

Mögliche Duplikat [Wie stelle ich die Dateien in einer JAR-Datei?] (https://stackoverflow.com/questions/1429172/how-do-i-list-the-files-inside-a-jar-file) – leetwinski

+0

Keine von denen zeigen entweder 1) eine einfache Möglichkeit, dies zu tun 2) eine Bibliothek, die das tut. Ich weigere mich zu akzeptieren, dass die Antwort darauf eine riesige Menge Java-Code ist. – siltalau

+0

gut .. es ist eine Art triviale Aufgabe, Java-Code zu clojure zu übersetzen. – leetwinski

Antwort

2

hier ist der Hafen von Code aus der Java-spezifischen Antwort:

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

zu einem Hauptnamensraum gesetzt wird und mit Glas laufen ausgeben alle Pfade im /resources/a Ordner ..

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

Auch einige schnelle Recherchen führen mich zu dieser Bibliothek:

es verkürzt den Code, erfordert aber auch einige Abhängigkeiten für das Projekt (ich denke, es nicht wünschenswert sein könnte):

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

und der Code ist so etwas wie dieses:

(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

Ich habe das als die richtige Antwort akzeptiert - was es technisch ist. Die Komplexität der Lösung sagt mir, dass ich versuche, das Falsche vollständig zu machen. – siltalau

0

Ein anderer Ansatz (aber ich muss zugeben, dass es nicht das Gefühl, völlig zufriedenstellend) ist es, den Inhalt zur Kompilierzeit zu lesen. Angenommen, Sie haben eine Funktion list-files, dass Sie die Liste aus dem Projekt Stammverzeichnis gibt:

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

oder

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