私はClojureプロジェクト(GUIアプリケーション)でLeiningenを使用しており、プロジェクトルートの下に「resources」ディレクトリを作成して、アプリが使用する画像を保持しています。
テスト中にアプリをローカルで実行している場合、相対パス「resources/logo.png」を使用して画像を取得しますが、これは正常に機能します。しかし、Leiningenを使用してuberjarを作成すると、LeiningenはJARファイルのリソースフォルダーのファイルをJARのルートフォルダーに配置するため、リソースファイルへの参照は機能しなくなります。
ライニンゲンを使用してこのようなリソースにアクセスする正しい方法は何ですか?
前の回答者(skuro)は、クラスパスからファイルを取得する必要があると指摘しました。もう少し掘り下げた後、これは私の場合に有効な解決策のようです:
(.getFile (clojure.Java.io/resource "foo.png"))
Kevin Albrechtの答えに対する単なる構文糖:
(require '[clojure.Java.io :as io])
(-> "foo.png" io/resource io/file)
これはOPの質問に直接答えているわけではありませんが、 skuro触れた 彼の最後の段落で非常に便利です。つまり、開発中にクラスパスでリソースを利用可能にしますが、リリースjar /ユーバージャー。
その理由は、たとえば/etc
の下に構成ファイルを配置するなど、jarの外部にリソースを個別に配置し、そのようなリソースフォルダーをクラスパスにリストすることにより、実行時にそれらにリンクできるからです。
:resource-paths
を削除します。:profiles {:dev {:resource-paths ["src/main/resources"]}}
この方法では、開発中にクラスパスでリソースを使用できます(コンパイル、テスト、repl)が、リリースjarには含まれません。
代替として、アプリケーションアイコンやグラフィックスなどの一部のリソースをリリースjarにバンドルしたい場合がありますが、構成ファイルなどの他のリソースはバンドルしません。その場合、resourcesフォルダーをサブディレクトリーに分割し、トップレベルに含めるものを宣言し、残りをdev
プロファイルの下に宣言します。
:resource-paths ["src/main/resources/icons"
"src/main/resources/images"]
:profiles {:dev {:resource-paths ["src/main/resources/config"]}}
上記の方法を使用すると、ファイルシステム上ではなく、クラスパス( Kevin および Valerii で示されているように)でリソースを検索することで、開発中と本番の両方でリソースを均一に参照できます:
(require '[clojure.Java.io :as jio])
(jio/file (jio/resource "relative/path/to/resource.xml"))
開発中、Leingingenはクラスパスにトップレベルとdev
プロファイルリソースの両方を含めます。リリースされたランタイムの場合、JREのクラスパスを自分で設定する必要があります。
Java -cp "/etc/myapp:/usr/local/lib/myapp.jar" myapp.core $*
また、代わりに、実際にはすべてのリソースをjarに含めることができます。そうすることで、含まれているリソースがデフォルトとして使用されます。 .jarファイルが構成フォルダー(例では/etc/myapp
)の後に来るようにクラスパスをセットアップすると、構成フォルダーの下にある同じ相対リソースパスを持つリソースファイルが、瓶。
ライニンゲンは、フォルダのレイアウトがわずかに異なる、Mavenのリソースの規則を取り入れています。このルールは、resources
フォルダーをコンパイル時のクラスパスルートとして使用する必要があることを示しています。つまり、leiningenはjar内のルートロケーションにあるresources
フォルダー内のすべてのファイルを正しく配置します。
問題は、物理的な場所!=クラスパスの場所であるため、前者はアプリケーションをパッケージ化するときに変更されますが、後者は同じままです(classpath:/
)
クラスパスの場所に依存してファイルシステムリソースを見つけるか、jarからそれらを取り出して、予測可能なフォルダー(静的フォルダーまたは構成可能なフォルダー)に配置することをお勧めします。
私はまったく同じ問題を抱えていましたが、解決策はnotを使用してio/file
まったく。たとえば、これは私のアプリからの作業コードです:
(defn load-md [md]
(->
md
io/resource ;;clojure.Java.io
Slurp
mp
to-hiccup
html))
この例では、.getPath
または.getFile
は役に立たなかった。単にinput-stream
代わりに解決しました。
(defonce classifier
(-> "machine_learning/classifier.model"
resource
input-stream
helper/read))
それを行う良い方法。ご了承ください 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!
そしてプレスト!クラスパスを介してリソースファイルを読み取っています。