如何在Clojure中加载程序资源 [英] How to load program resources in Clojure

查看:130
本文介绍了如何在Clojure中加载程序资源的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



我试过的第一件事是类似

 (ClassLoader / getSystemResourceresources / myscript.js)



但是却找不到资源。





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

其中name是 / code>要加载的资源,但流是 nil



上下文类加载器与

  ... 

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

strem 始终为零。



将资源文件放置在程序中的每个目录中。



我已经查看了的语言来源,加载函数和运行时库,但不是获取。



任何帮助将不胜感激。 b
$ b

EDIT :这是一个更具体的例子。在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示例{

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无法创建转换器;
}
try {
return((Invocable)engine).invokeMethod(converter,makeHtml,
markdownString).toString
} catch(Exception e){
return转换失败;
}
}

public static void main(String [] args){
System.out.println(new Example()。transformMarkDown强调*,**强**));
}
}

当我创建项目时,包装入罐。运行时,程序输出< p> plain,< em> emphasis< / em>,< strong> strong< / strong>< / p> / p>

对Clojure的直译可能非常简单,但是我试图创建 InputStreamReader



编辑:自从帖子后添加了markdown标签

解决方案

这是目录结构。



继续使用OP中的脚本引擎示例,Clojure等效项将是:

 (ns com.domain。示例
(:gen-class)
(:import(java.io InputStreamReader))
(:import(javax.script ScriptEngineManager ScriptEngine)))

defn load-resource
[name]
(let [rsc-name(strcom / domain / resources /name)
thr(Thread / currentThread)
ldr getContextClassLoader thr)]
(.getResourceAsStream ldr rsc-name)))

(defn markdown-to-html
[mkdn]
ScriptEngineManager)
引擎(.getEngineByName managerjs)
是(InputStreamReader。 (load-resourceshowdown.js))
_(.eval engine is)
cnv-arg(strnew Showdown.converter()。makeHtml(\mkdn\ ))]
(.eval engine cnv-arg)))

(defn -main
[]
(println(markdown-to-htmlplain ,* emphasis *,** strong **)))

注意,资源的路径在Java版本中与 com / domain / scriptingtest / resources 相反, com / domain / resources 在clojure版本中,源文件 example.clj 位于 com / domain 中。在Java版本中,源文件 Example.java 位于 com / domain / scriptingtest 包中。 p>

在我的IDE(NetBeans)中设置项目时,Java项目向导会要求提供源代码的封装包。 Clojure插件,enclojure,要求一个命名空间,而不是一个包。我从来没有注意到差别。因此,目录结构中的off-by-one错误预期。


How do you load program resources such as icons, strings, graphical elements, scripts, and so on in a Clojure program? I am using a project layout similar to that in many Java projects where there is a "resources" directory hanging off of a "source" directory. A jar file is created from the source and includes the resources, but I can't seem to get the resources loaded as I would in Java.

The first thing I tried was something like

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

But could never find the resource.

You can do something similar with

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

where name is the name of the resource to load, but the stream is nil.

You can try using the context class loader with something like

...

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

But strem is always nil.

In frustration, I've tried placing the resource files in just about every directory in the program. They get copied into the jar correctly, but I still can't seem to load them.

I've looked at the language sources for the load function and the run-time library, but am not "getting" it.

Any help would be appreciated.

EDIT: Here's a more concrete example. In Java, if you wanted to convert MarkDown to HTML, you might use the showdown.js script and write something like:

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**"));
    }
}

when I create the project, it all gets compiled and packed into a jar. When run, the program outputs <p>plain, <em>emphasis</em>, <strong>strong</strong></p>

A literal translation to Clojure seems pretty straightforward, but I run into trouble trying to create the InputStreamReader -- I can't seem to write the code needed to find the script file in the jar.

Edit: Added "markdown" tag since the post gives two complete examples of approaches to processing markdown.

解决方案

It's the directory structure.

Continuing with the scripting engine example in the OP, a Clojure equivalent would be:

(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**")))

Note that the path to the resources is com/domain/resources for this code as opposed to com/domain/scriptingtest/resources in the Java version. In the clojure version, the source file, example.clj is in com/domain. In the Java version, the source file, Example.java is in the com/domain/scriptingtest package.

When setting up a project in my IDE, NetBeans, the Java project wizard asks for an enclosing package for the source. The Clojure plugin, enclojure, asks for a namespace, not a package. I had never noted that difference before. Hence the "off-by-one" error in the directory structure expected.

这篇关于如何在Clojure中加载程序资源的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆