2010-01-11 5 views
28

Wie laden Sie Programmressourcen wie Symbole, Zeichenfolgen, grafische Elemente, Skripte und so weiter in einem Clojure-Programm? Ich verwende ein Projekt-Layout, das dem in vielen Java-Projekten ähnlich ist, wo ein "Ressourcen" -Verzeichnis an einem "Quell" -Verzeichnis hängt. Eine JAR-Datei wird aus der Quelle erstellt und enthält die Ressourcen, aber ich kann nicht scheinen, dass die Ressourcen wie in Java geladen werden.Wie Programmressourcen in Clojure geladen werden

Das erste, was ich versuchte, war so etwas wie

(ClassLoader/getSystemResource "resources/myscript.js") 

konnte aber nie die Ressource finden.

Sie können etwas Ähnliches tun mit

... 
    (let [cls (.getClass net.mydomain.somenamespace) 
     strm (.getResourceAsStream cls name)  ] 
... 

wobei Name der name der Ressource zu laden, aber der Strom ist nil.

Sie können versuchen, den Kontext Class Loader mit mit so etwas wie

... 

(let [thr (Thread/currentThread) 
     ldr (.getContextClassLoader thr) 
     strem (.getResourceAsStream ldr name)] 
... 

Aber strem ist immer gleich Null.

In Frustration habe ich versucht, die Ressourcen-Dateien in fast jedem Verzeichnis im Programm zu platzieren. Sie werden korrekt in das Glas kopiert, aber ich kann sie immer noch nicht laden.

Ich habe die Sprachquellen für die load-Funktion und die Laufzeitbibliothek angeschaut, aber ich "bekomme" es nicht.

Jede Hilfe wäre willkommen.

EDIT: Hier ist ein konkreteres Beispiel. In Java, wenn Sie Markdown in HTML konvertieren wollen, könnten Sie die showdown.js Skript verwenden und schreiben so etwas wie:

package scriptingtest; 

import java.io.InputStreamReader; 
import javax.script.Invocable; 
import javax.script.ScriptEngine; 
import javax.script.ScriptEngineManager; 

public class Example { 

    private Object converter; 

    public String transformMarkDown(String markdownString) { 
     ScriptEngineManager manager = new ScriptEngineManager(); 
     ScriptEngine engine = manager.getEngineByName("js"); 
     try { 
      engine.eval(new InputStreamReader(getClass().getResourceAsStream(
        "resources/showdown.js"))); 
      converter = engine.eval("new Showdown.converter()"); 
     } catch (Exception e) { 
      return "Failed to create converter"; 
     } 
     try { 
      return ((Invocable) engine).invokeMethod(converter, "makeHtml", 
        markdownString).toString(); 
     } catch (Exception e) { 
      return "Conversion failed"; 
     } 
    } 

    public static void main(String[] args) { 
     System.out.println(new Example().transformMarkDown("plain, *emphasis*, **strong**")); 
    } 
} 

, wenn ich das Projekt zu erstellen, das alles in ein Glas gesammelt und verpackt wird. Wenn er ausgeführt wird, gibt das Programm <p>plain, <em>emphasis</em>, <strong>strong</strong></p>

Eine wörtliche Übersetzung Clojure ziemlich einfach scheint, aber ich laufe in Mühe versuchen, die erstellen InputStreamReader - ich kann nicht scheinen, um den Code zu schreiben, benötigt die Skriptdatei in das Glas zu finden .

Bearbeiten: Hinzugefügt "Markdown" -Tag seit der Post gibt zwei vollständige Beispiele für Ansätze zur Verarbeitung Markdown.

+0

könnten Sie ein Beispiel in Java hinzufügen? –

+0

@arthur: Ein konkreteres Beispiel in Java hinzugefügt. Wie würdest du dasselbe in Clojure erreichen? – clartaq

Antwort

5

Es ist die Verzeichnisstruktur.

mit dem Scripting-Engine Beispiel im OP Weiterbildung, ein Clojure äquivalent wäre:

(ns com.domain.example 
    (:gen-class) 
    (:import (java.io InputStreamReader)) 
    (:import (javax.script ScriptEngineManager ScriptEngine))) 

(defn load-resource 
    [name] 
    (let [rsc-name (str "com/domain/resources/" name) 
     thr (Thread/currentThread) 
     ldr (.getContextClassLoader thr)] 
    (.getResourceAsStream ldr rsc-name))) 

(defn markdown-to-html 
    [mkdn] 
    (let [manager (new ScriptEngineManager) 
     engine (.getEngineByName manager "js") 
     is (InputStreamReader. (load-resource "showdown.js")) 
     _ (.eval engine is) 
     cnv-arg (str "new Showdown.converter().makeHtml(\"" mkdn "\")")] 
    (.eval engine cnv-arg))) 

(defn -main 
    [] 
    (println (markdown-to-html "plain, *emphasis*, **strong**"))) 

Beachten Sie, dass der Pfad zu den Ressourcen ist com/domain/resources für diesen Code wie in der Java-Version zu com/domain/scriptingtest/resources gegenüber. In der Clojure-Version befindet sich die Quelldatei example.clj in com/domain. In der Java-Version befindet sich die Quelldatei Example.java im Paket com/domain/scriptingtest.

Beim Einrichten eines Projekts in meiner IDE, NetBeans, fragt der Java-Projektassistent nach einem umschließenden Paket für die Quelle. Das Clojure-Plugin enclojure fragt nach einem Namespace, nicht nach einem Paket. Ich habe diesen Unterschied vorher nie bemerkt. Daher der "off-by-one" -Fehler in der Verzeichnisstruktur erwartet. verwenden

3

Ich legte die Datei in testpkg/test.txt (relativ zum aktuellen Verzeichnis).

Code:

(def x 5) 
(def nm "testpkg/test.txt") 
(def thr (Thread/currentThread)) 
(def ldr (.getContextClassLoader thr)) 
(def strem (.getResourceAsStream ldr nm)) 
(def strem2 (ClassLoader/getSystemResource nm)) 
(. System/out (println "First Approach:")) 
(. System/out (println strem)) 
(. System/out (println)) 
(. System/out (println)) 
(. System/out (println "Second Approach:")) 
(. System/out (println strem2)) 

$ java -cp \; clojure.jar clojure.main test.clj

Erster Ansatz:. [email protected]

Zweiter Ansatz: Datei:/C: /jsight/javadevtools/clojure-1.1.0/testpkg/test.txt

+0

Ja, dies kann bei der REPL funktionieren. Aber ist es möglich, dies in eine Funktion zu setzen, eine Klasse zu generieren, die kompilierte Klasse zusammen mit den Ressourcen in ein jar zu schreiben, die Klasse im jar auszuführen und die Ressourcen erfolgreich laden zu lassen? Tut mir leid, wenn ich nicht wusste, ob ich zu einer Klasse kompilieren und ein Glas bauen wollte. Englisch ist nur meine zweite Sprache. Verwirrung ist meine erste ;-) – clartaq

+0

Der Code funktioniert auf die gleiche Weise. – jsight

+0

Nicht sicher, warum dies abgelehnt wurde, aber ich gebe es ein +1, da die Ausgabe mich in die benötigte Verzeichnisstruktur angedeutet hat. – clartaq

49
(clojure.java.io/resource "myscript.js")