如何在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