如何在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总是零。

令人沮丧的是,我尝试将资源文件放在程序的几乎每个目录中。 它们被正确地复制到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中。 运行时,程序输出

plain, emphasis, strong

对Clojure的字面翻译似乎非常简单,但是我在尝试创建InputStreamReader遇到了麻烦 – 我似乎无法编写在jar中查找脚本文件所需的代码。

编辑 :添加了“markdown”标签,因为该post提供了两个处理降价处理方法的完整示例。

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

这是目录结构。

继续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 。 在clojure版本中,源文件example.clj位于com/domain 。 在Java版本中,源文件Example.java位于com/domain/scriptingtest包中。

在我的IDE NetBeans中设置项目时,Java项目向导会要求提供源的封装包。 Clojure插件,包装,请求命名空间,而不是包。 我之前从未注意到这种差异。 因此,期望的目录结构中的“off-by-one”错误。

你也可以使用clojure.lang.RT / baseLoader

 (defn serve-public-resource [path] (.getResourceAsStream (clojure.lang.RT/baseLoader) (str "public/" path))) 

我将文件放在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