如何在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
总是零。
令人沮丧的是,我尝试将资源文件放在程序的几乎每个目录中。它们被正确地复制到jar中,但我似乎仍然无法加载它们。
我查看了load
函数和运行时库的语言来源,但我没有“得到”它。
任何帮助都将不胜感激。
编辑:这是一个更具体的例子。在Java中,如果要将MarkDown转换为HTML,可以使用showdown.js
脚本并编写如下内容:
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**"));
}
}
当我创建项目时,它们都被编译并打包到jar中。运行时,程序会输出<p>plain, <em>emphasis</em>, <strong>strong</strong></p>
对Clojure的字面翻译似乎非常简单,但是我在尝试创建InputStreamReader
时遇到了麻烦 - 我似乎无法编写在jar中查找脚本文件所需的代码。
修改:添加了“降价”标记,因为该帖子提供了两个处理降价处理方法的完整示例。
答案 0 :(得分:50)
(clojure.java.io/resource "myscript.js")
答案 1 :(得分:5)
这是目录结构。
继续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
,而Java版本中的com/domain/scriptingtest/resources
则为example.clj
。在clojure版本中,源文件com/domain
位于Example.java
中。在Java版本中,源文件com/domain/scriptingtest
位于{{1}}包中。
在我的IDE NetBeans中设置项目时,Java项目向导会要求提供源的封装包。 Clojure插件,包括命名空间,而不是包。我之前从未注意到这种差异。因此,期望的目录结构中出现“off-by-one”错误。
答案 2 :(得分:4)
您也可以使用clojure.lang.RT/baseLoader
(defn serve-public-resource [path]
(.getResourceAsStream (clojure.lang.RT/baseLoader) (str "public/" path)))
答案 3 :(得分:3)
我将文件放在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
第一种方法: java.io.BufferedInputStream@1549f94
第二种方法: 文件:/ C:/jsight/javadevtools/clojure-1.1.0/testpkg/test.txt