Как загрузить ресурсы программы в Clojure
Как вы загружаете программные ресурсы, такие как значки, строки, графические элементы, скрипты и т.д. в программе Clojure? Я использую макет проекта, аналогичный такому во многих проектах Java, где есть каталог ресурсов, зависающий от "исходного" каталога. Файл jar создается из источника и включает в себя ресурсы, но я не могу получить загруженные ресурсы, как я был бы в Java.
Первое, что я пробовал, было что-то вроде
(ClassLoader/getSystemResource "resources/myscript.js")
Но никогда не мог найти ресурс.
Вы можете сделать что-то подобное с
...
(let [cls (.getClass net.mydomain.somenamespace)
strm (.getResourceAsStream cls name) ]
...
где name является name
ресурса для загрузки, но поток nil
.
Вы можете попробовать использовать загрузчик класса контекста с чем-то вроде
...
(let [thr (Thread/currentThread)
ldr (.getContextClassLoader thr)
strem (.getResourceAsStream ldr name)]
...
Но strem
всегда равно nil.
В отчаянии я попытался разместить файлы ресурсов практически в каждом каталоге программы. Они правильно копируются в банку, но я все еще не могу их загрузить.
Я просмотрел источники языка для функции load
и библиотеки времени выполнения, но я не "получаю" ее.
Любая помощь будет оценена.
EDIT. Здесь приведен более конкретный пример. В Java, если вы хотите преобразовать MarkDown в HTML, вы можете использовать showdown.js
script и написать что-то вроде:
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**"));
}
}
когда я создаю проект, он все компилируется и упаковывается в банку. При запуске программа выводит <p>plain, <em>emphasis</em>, <strong>strong</strong></p>
Дословный перевод на Clojure кажется довольно простым, но я столкнулся с трудностями при создании InputStreamReader
- я не могу написать код, необходимый для поиска файла script в банке.
Изменить: добавлен тег "markdown", поскольку сообщение дает два полных примера подходов к обработке уценки.
Ответы
Ответ 1
Это структура каталогов.
Продолжая пример сценария сценария в OP, эквивалент Clojure:
(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**")))
Обратите внимание, что путь к ресурсам com/domain/resources
для этого кода, а не com/domain/scriptingtest/resources
в версии Java. В версии Clojure исходный файл example.clj
находится в com/domain
. В версии Java исходный файл Example.java
находится в пакете com/domain/scriptingtest
.
При настройке проекта в моей среде IDE, NetBeans, мастер проекта Java запрашивает закрытый пакет для источника. Плагин Clojure, enclojure, запрашивает пространство имен, а не пакет. Раньше я никогда не замечал этой разницы. Следовательно, ожидаемая ошибка "по-одному" в структуре каталогов.
Ответ 2
(clojure.java.io/resource "myscript.js")
Ответ 3
вы также можете использовать clojure.lang.RT/baseLoader
(defn serve-public-resource [path]
(.getResourceAsStream (clojure.lang.RT/baseLoader) (str "public/" path)))
Ответ 4
Я поместил файл в testpkg/test.txt(относительно текущего каталога).
код:
(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
Первый подход: [email protected]
Второй подход: Файл:/C:/jsight/javadevtools/ clojure -1.1.0/testpkg/test.txt