如何在 Clojure 中加载程序资源

2022-09-01 13:53:06

如何在Clojure程序中加载程序资源,如图标,字符串,图形元素,脚本等?我正在使用类似于许多Java项目中的项目布局,其中有一个“资源”目录悬挂在“源”目录上。jar文件是从源代码创建的,其中包含资源,但我似乎无法像在Java中那样加载资源。

我尝试的第一件事是这样的

(ClassLoader/getSystemResource "resources/myscript.js")

但永远找不到资源。

您可以使用以下命令执行类似操作

...
  (let [cls (.getClass net.mydomain.somenamespace)
        strm (.getResourceAsStream cls name)        ]
...

其中 name 是要加载的资源的 ,但流是 。namenil

您可以尝试将上下文类装入器与类似的东西一起使用

...

(let [thr (Thread/currentThread)
      ldr (.getContextClassLoader thr)
      strem (.getResourceAsStream ldr name)]
...

但总是为零。strem

在沮丧中,我尝试将资源文件放在程序中的几乎每个目录中。它们被正确地复制到罐子里,但我似乎仍然无法加载它们。

我已经查看了函数和运行时库的语言源,但没有“获取”它。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**"));
    }
}

当我创建项目时,它都被编译并打包到一个罐子里。运行时,程序输出<p>plain, <em>emphasis</em>, <strong>strong</strong></p>

对Clojure的直译似乎很简单,但我在尝试创建时遇到了麻烦 - 我似乎无法编写在jar中找到脚本文件所需的代码。InputStreamReader

编辑:添加了“markdown”标签,因为该帖子给出了两个处理markdown方法的完整示例。


答案 1
(clojure.java.io/resource "myscript.js")

答案 2

这是目录结构。

继续使用 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**")))

请注意,资源的路径适用于此代码,而不是 Java 版本中的路径。在 clojure 版本中,源文件位于 。在 Java 版本中,源文件位于包中。com/domain/resourcescom/domain/scriptingtest/resourcesexample.cljcom/domainExample.javacom/domain/scriptingtest

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


推荐