代码之家  ›  专栏  ›  技术社区  ›  clartaq

如何在clojure中加载程序资源

  •  28
  • clartaq  · 技术社区  · 15 年前

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

    我试过的第一件事是

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

    但永远找不到资源。

    你可以做一些类似的事情

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

    名字在哪 name 要加载的资源,但流是 nil .

    您可以尝试使用上下文类加载器

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

    但是 strem 总是零。

    沮丧的是,我试着将资源文件放在程序中几乎所有的目录中。它们被正确地复制到jar中,但我似乎仍然无法加载它们。

    我已经看过了 load 函数和运行时库,但不是“获取”它。

    任何帮助都将不胜感激。

    编辑 :这里有一个更具体的例子。在Java中,如果你想把它转换成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中。运行时,程序输出 <p>plain, <em>emphasis</em>, <strong>strong</strong></p>

    对clojure的直译似乎非常简单,但是我在尝试创建 InputStreamReader --我似乎无法编写在jar中找到脚本文件所需的代码。

    编辑 :添加了“markdown”标记,因为文章给出了处理markdown的两个完整方法示例。

    4 回复  |  直到 13 年前
        1
  •  50
  •   Joe Snikeris    13 年前
    (clojure.java.io/resource "myscript.js")
    
        2
  •  5
  •   clartaq    15 年前

    这是目录结构。

    继续操作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/resources 在Java版本中。在clojure版本中,源文件, example.clj 是在 com/domain . 在Java版本中,源文件, Example.java 是在 com/domain/scriptingtest 包裹。

    在ide netbeans中设置项目时,java项目向导要求为源代码提供一个封闭包。clojure插件enclojure要求一个名称空间,而不是一个包。我以前从未注意到这种差异。因此,在目录结构中应该出现“off by one”错误。

        3
  •  4
  •   miaubiz    14 年前

    你也可以使用 clojure.lang.RT/baseLoader

    (defn serve-public-resource [path]
      (.getResourceAsStream (clojure.lang.RT/baseLoader) (str "public/" path))) 
    
        4
  •  3
  •   jsight TaherT    15 年前

    我将文件放在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-C.\Culjul.Jar Culjur.Mest.Test.CLJ

    第一种方法: Java.IO .BuffReDeEndoSturs@ 1549 F94.

    第二种方法: 文件:/c:/jsight/javadevtools/clojure-1.1.0/testpkg/test.txt