Clojure应用程序中的资源

Clojure应用程序中的资源,clojure,leiningen,Clojure,Leiningen,我在Clojure项目(一个GUI应用程序)中使用Leiningen,并在项目根目录下创建了一个“resources”目录,以保存我的应用程序使用的图像 在测试过程中,当我在本地运行我的应用程序时,我使用相对路径“resources/logo.png”获取图像,这很好。但是,当我使用Leiningen构建uberjar时,Leiningen将资源文件夹中的文件放在JAR的根文件夹中,因此我对资源文件的引用不再有效 使用Leiningen访问此类资源的正确方法是什么?Leiningen借用了mav

我在Clojure项目(一个GUI应用程序)中使用Leiningen,并在项目根目录下创建了一个“resources”目录,以保存我的应用程序使用的图像

在测试过程中,当我在本地运行我的应用程序时,我使用相对路径“resources/logo.png”获取图像,这很好。但是,当我使用Leiningen构建uberjar时,Leiningen将资源文件夹中的文件放在JAR的根文件夹中,因此我对资源文件的引用不再有效


使用Leiningen访问此类资源的正确方法是什么?

Leiningen借用了maven的资源惯例,文件夹布局略有不同。该规则规定
resources
文件夹必须用作编译时类路径根,这意味着leiningen正确地将
resources
文件夹中的所有文件放在jar的根位置

问题在于物理位置!=类路径位置,这样当您打包应用程序时,前者会发生更改,而后者保持不变(
classpath:///code>)

您最好依靠类路径位置来查找文件系统资源,或者将它们从jar中取出并放入一个可预测的文件夹中,可以是静态文件夹,也可以是可配置文件夹。

前面的回答者(skuro)指出,我需要从类路径获取文件。在进一步挖掘之后,这似乎是适用于我的案例的解决方案:

(.getFile (clojure.java.io/resource "foo.png"))

对于凯文·阿尔布雷希特的回答,我只想说一句:

(require '[clojure.java.io :as io])

(-> "foo.png" io/resource io/file) 

做这件事的好方法。请注意,
io/file
返回一个java
file
对象,然后可以将该对象传递给
slurp
,等等:

(ns rescue.core
  (:require [clojure.java.io :as io] ))

(def data-file (io/file
                 (io/resource 
                   "hello.txt" )))
(defn -main []
  (println (slurp data-file)) )
如果在lein项目目录中执行以下操作:

> echo "Hello Resources!" > resources/hello.txt
> lein run
Hello Resources!

还有普雷斯托!您正在通过类路径读取资源文件。

这并不是直接回答OP的问题,而是在他的最后一段中,这可能非常有用,即在开发过程中在类路径上提供资源,但不将其包含在发布jar/uberjar中

这样做的原因是,您可以将资源单独放置在jar之外,例如将配置文件放置在
/etc
下,然后在运行时通过在类路径上列出这些资源文件夹来链接到它们

project.clj中的定义
  • 从project.clj中删除顶级
    :资源路径
    
    
  • 在顶层的project.clj中添加以下行:
:profiles{:dev{:resource path[“src/main/resources”]}
这样,资源将在开发期间(编译、测试、repl)在类路径上可用,但不会包含在发布JAR中

作为替代方案,您可能希望将一些资源(如应用程序图标和图形)与发布jar捆绑在一起,但不希望将其他资源(如配置文件)捆绑在一起。在这种情况下,您可以将resources文件夹拆分为子目录,并声明希望在顶层包含的子目录,而其余的子目录则位于
dev
概要文件下:

:资源路径[“src/main/resources/icons”
“src/main/resources/images”]
:profiles{:dev{:resourcepaths[“src/main/resources/config”]}
在代码中引用资源 使用上述方法,您可以在开发和生产期间统一引用资源,方法是在类路径(如和所示)上查看资源,而不是直接在文件系统上查看资源:

(需要“[clojure.java.io:as jio]”
(jio/file(jio/resource“relative/path/to/resource.xml”))
运行时类路径 在开发过程中,Leiningen将包括类路径上的顶层和
dev
概要文件资源。对于发布的运行时,您必须自己配置JRE的类路径:

java-cp”/etc/myapp:/usr/local/lib/myapp.jar“myapp.core$*

另外,您也可以将所有资源保留在jar中。这样,所包含的资源将用作默认值。如果设置类路径,使.jar文件位于配置文件夹之后(
/etc/myapp
,在本例中),那么配置文件夹下具有相同相对资源路径的资源文件将优先于jar中包含的资源文件。

,使用
.getPath
.getFile
没有帮助。只需使用
输入流
即可解决此问题

(require '[clojure.java.io :as io])

(defonce classifier
  (-> "machine_learning/classifier.model"
      io/resource
      io/input-stream
      helper/read))

我遇到了完全相同的问题,解决方案是根本不使用
io/file
。例如,这是我的应用程序的工作代码:

(defn load-md [md]
  (->
   md
   io/resource ;;clojure.java.io
   slurp
   mp
   to-hiccup
   html))

(.getPath (io/resource "file")) 
至->


使它在我的例子中起作用,因为
str
文件:/…路径..
添加到路径。

(.getPath)
更准确,因为
(.getFile)
还附加了可能存在的查询参数,这些参数不应该存在于资源URL中。对我来说,它仍然不起作用
(io/resource“file.png”)
返回
nil
,但
file.png
包含在
jar
文件中。所以我不确定发生了什么
.getFile
只会导致NPE,因此无法在其上使用
slurp
。找到我的问题。我正在使用ring从
resources/../
服务一个目录,它在开发过程中工作。但是在我构建了一个
jar
之后,
ring.util.response/resource response
中的验证失败了。因此,它返回
nil
,因为它试图检查规范路径,但它不匹配,因为它位于
jar
中。请检查我的答案。我也有同样的问题。是否有一个资源布局或使用它的示例项目的好例子?在任何人开始对文件发出声音之前,请注意,一旦打包到jar中,这将不起作用。slurp可以处理资源本身:请更具体一些。您可能是指
clojure.java.io/resource
,但是
resource
可以是任何东西。同样的道理也适用于
(str (io/resource "file"))