如何在Clojure程序中加载程序资源,例如图标,字符串,图形元素,脚本等?我使用的项目布局类似于许多Java项目中的布局,在Java项目中,“资源”目录挂在“源”目录上。一个jar文件是从源代码创建的,包括资源,但是我似乎无法像在Java中那样加载资源。
我尝试的第一件事是
(ClassLoader/getSystemResource "resources/myscript.js")
但是永远找不到资源。
您可以使用类似的方法
... (let [cls (.getClass net.mydomain.somenamespace) strm (.getResourceAsStream cls name) ] ...
其中name是name要加载的资源的名称,而流是nil。
name
nil
您可以尝试将上下文类加载器与类似
... (let [thr (Thread/currentThread) ldr (.getContextClassLoader thr) strem (.getResourceAsStream ldr name)] ...
但是strem总是零。
strem
无奈的是,我试图将资源文件几乎放置在程序的每个目录中。它们被正确地复制到了jar中,但是我似乎还是无法加载它们。
我已经看过该load函数和运行时库的语言源,但并未“获取”它。
load
任何帮助,将不胜感激。
编辑 :这是一个更具体的例子。在Java中,如果要将MarkDown转换为HTML,则可以使用该showdown.js脚本并编写如下内容:
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>
<p>plain, <em>emphasis</em>, <strong>strong</strong></p>
从字面意义上翻译成Clojure似乎很简单,但是尝试创建InputStreamReader-似乎无法写出在jar中找到脚本文件所需的代码时遇到了麻烦。
InputStreamReader
编辑 :添加了“ markdown”标记,因为该帖子给出了两个处理markdown方法的完整示例。
这是目录结构。
继续操作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/resourcesJava版本。在clojure版本中,源文件example.clj位于中com/domain。在Java版本中,源文件Example.java位于com/domain/scriptingtest软件包中。
com/domain/resources
com/domain/scriptingtest/resources
example.clj
com/domain
Example.java
com/domain/scriptingtest
在我的IDE NetBeans中设置项目时,Java项目向导会要求提供源的封装包。Clojure插件enclojure要求一个名称空间,而不是一个包。我以前从未注意到这种差异。因此,预期的目录结构中的“ off-by-one”错误。