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)]
...
But strem
is always nil。
沮丧的是,我尝试将资源文件放置在程序中的几乎每个目录中。它们被正确复制到罐子中,但我似乎仍然无法加载它们。
我已经查看了 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”标签,因为该帖子给出了处理 Markdown 的方法的两个完整示例。
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这是目录结构。
继续 OP 中的脚本引擎示例,Clojure 等效项将是:
请注意,此代码的资源路径是 com/domain/resources,而不是 com/domain/scriptingtest Java 版本中的 /resources 。在 clojure 版本中,源文件
example.clj
位于com/domain
中。在 Java 版本中,源文件Example.java
位于com/domain/scriptingtest
包中。在我的 IDE NetBeans 中设置项目时,Java 项目向导要求提供源的封闭包。 Clojure 插件 enclojure 需要命名空间,而不是包。我以前从未注意到这种差异。因此,目录结构中会出现“相差一”错误。
It's the directory structure.
Continuing with the scripting engine example in the OP, a Clojure equivalent would be:
Note that the path to the resources is
com/domain/resources
for this code as opposed tocom/domain/scriptingtest/resources
in the Java version. In the clojure version, the source file,example.clj
is incom/domain
. In the Java version, the source file,Example.java
is in thecom/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.lang.RT/baseLoader
you can also use clojure.lang.RT/baseLoader
我将文件放在 testpkg/test.txt 中(相对于当前目录)。
代码:
$ java -cp .\;clojure.jar clojure.main test.clj
I placed the file in testpkg/test.txt (relative to current directory).
Code:
$ java -cp .\;clojure.jar clojure.main test.clj