• 追加された行はこの色です。
  • 削除された行はこの色です。
TITLE:ClassLoaderでリソース(URL)を取得
#navi(../)
RIGHT:Posted by [[aterai]] at 2006-05-22
*ClassLoaderでリソース(URL)を取得 [#v8918bae]
クラスパスからのエントリ(相対パス風)を使って、ClassLoaderからURLを取得します。
---
category: swing
folder: ClassLoader
title: ClassLoaderでリソース(URL)を取得
tags: [ClassLoader, Resource, URL]
author: aterai
pubdate: 2006-05-22T09:59:23+09:00
description: クラスパスからのエントリ(相対パス風)を使って、ClassLoaderからURLを取得します。
image: https://lh3.googleusercontent.com/_9Z4BYR88imo/TQTI-UTFN-I/AAAAAAAAATo/6sdQoVO0Kc4/s800/ClassLoader.png
---
* 概要 [#summary]
クラスパスからのエントリ(相対パス風)を使って、`ClassLoader`から`URL`を取得します。

-&jnlp;
-&jar;
-&zip;
#download(https://lh3.googleusercontent.com/_9Z4BYR88imo/TQTI-UTFN-I/AAAAAAAAATo/6sdQoVO0Kc4/s800/ClassLoader.png)

//#screenshot
#ref(http://lh3.ggpht.com/_9Z4BYR88imo/TQTI-UTFN-I/AAAAAAAAATo/6sdQoVO0Kc4/s800/ClassLoader.png)

**サンプルコード [#jcd0714c]
#code{{
* サンプルコード [#sourcecode]
#code(link){{
URL url = getClass().getClassLoader().getResource("example/test.png");
//URL url = getClass().getResource("test.png");
// URL url = Thread.currentThread().getContextClassLoader().getResource("example/test.png");
// URL url = getClass().getResource("test.png");
JLabel icon = new JLabel(new ImageIcon(url));
JLabel path = new JLabel(url.toString());
}}

**解説 [#fc02caf2]
ClassLoaderを使用して、位置に依存しない方法でリソース(URL)を取得します。
* 解説 [#explanation]
`ClassLoader`を使用して、位置に依存しない方法でリソース(`URL`)を取得します。

以下、".\target\classes\example\test.png"にある画像ファイルのURLをクラスパスからのエントリ(相対パス風)を使って取得する場合を考えます。
- 例えば`new ImageIcon(String filename)`のようにファイルパスを文字列で指定した場合、このファイルパスが位置(カレントディレクトリ)に依存しているため、実行時に別のディレクトリから起動したり、`jar`ファイルにまとめたりするとファイルが参照できなくなる

以下、`.\target\classes\example\test.png`にある画像ファイルの`URL`をクラスパスからのエントリ(相対パス風)を使って取得する場合を考えます。

上記のサンプルに添付しているバッチファイルでは、クラスパスは次のように設定しています。
 java -classpath ".\target\classes" example.MainPanel

ClassLoader#getResourceメソッドを使用する場合は、以下のようにクラスパスからのエントリを使用します。このエントリは、相対パス風で頭に/は付けず、/区切りで記述します。
`ClassLoader#getResource`メソッドを使用する場合は、以下のようにクラスパスからのエントリを使用します。このエントリは、相対パス風で頭に`/`は付けず、`/`区切りで記述します。

#code{{
getClass().getClassLoader().getResource("example/test.png");
//ただし、getClass().getClassLoader().getResource("./example/test.png");
//だとjar内にパッケージした時うまくいかない。
// ただし、getClass().getClassLoader().getResource("./example/test.png");
// だとjar内にパッケージした場合で失敗する
}}

----
ClassLoaderからでは無く、Class#getResourceメソッドを使う方法もあります。この場合、エントリ名がメソッド内で以下のように変換されます。
-相対パス風(頭に/が付かない)の場合
--"." が "/" に変換された、modified_package_nameが名前の前に補完される
--例えば、com.example.Testクラスなら、"com/example/"
--このサンプルではexample.MainPanelクラスなので、"example/"が補完されて、"example/test.png"になる
`ClassLoader`からでは無く、`Class#getResource`メソッドを使う方法もあります。この場合、エントリ名がメソッド内で以下のように変換されます。

- 相対パス風(頭に`/`が付かない)の場合
-- `.`が`/`に変換された、`modified_package_name`が名前の前に補完される
-- 例えば、`com.example.Test`クラスなら、`com/example/`
-- このサンプルでは`example.MainPanel`クラスなので、`example/`が補完されて、`example/test.png`になる

#code{{
getClass().getResource("test.png");
//getClass().getClassLoader().getResource("example/test.png");と同じ
getClass().getResource("test.png"); //or MainPanel.class.getResource("test.png");
// getClass().getClassLoader().getResource("example/test.png");と同じ
}}

-絶対パス風(頭に/が付く)の場合
--modified_package_nameは補完せず、頭の "/" は削除される
- 絶対パス風(頭に`/`が付く)の場合
-- `modified_package_name`は補完せず、頭の`/`は削除される

#code{{
getClass().getResource("/test.png");
//getClass().getClassLoader().getResource("test.png");と同じ
//上記の相対パスと同じリソースを取得する場合は、
//getClass().getResource("/example/test.png");としなくてはならない
// getClass().getClassLoader().getResource("test.png");と同じ
// 上記の相対パスと同じリソースを取得する場合は、
// getClass().getResource("/example/test.png");としなくてはならない
}}

----
クラスパス上にs同名のリソースが複数存在する場合は、最初に見つかったものが使用されます。
+src.zipをダウンロードして適当な場所に展開する
+c:\temp\example\test.png という画像ファイルを別途用意する
+1.で展開したフォルダにあるrun.batの6行目(クラスパス)を以下のように変更
 set LOCALCLASSPATH=c:\temp;.\target\classes
+ant でコンパイルして、修正したrun.batで実行
クラスパス上に同名のリソースが複数存在する場合は、最初に見つかったものが使用されます。

この場合、src.zipに元々入っていた「適当な場所/test.png」ではなく、「file:/C:/temp/example/test.png」というURLがgetResourceで取得できます。
- `src.zip`をダウンロードして適当な場所に展開する
- `c:\temp\example\test.png`という画像ファイルを別途用意する
- 展開したフォルダにある`run.bat`のクラスパスを以下のように変更(`c:\temp`を最初に追加)

**参考リンク [#o584993f]
-[http://java.sun.com/javase/ja/6/docs/ja/technotes/guides/lang/resources.html 位置に依存しない方法でのリソースへのアクセス]
-[http://java.sun.com/docs/books/tutorial/uiswing/components/icon.html#getresource Loading Images Using getResource]
#code{{
set MAIN_CLASS=example.MainPanel
rem set CLASSPATH=.\target\classes
set CLASSPATH=c:\temp;.\target\classes
}}

**コメント [#z19691a0]
- 「クラスパスからのパス」などの意味が分かり辛いので、[http://java.sun.com/javase/ja/6/docs/ja/api/java/net/JarURLConnection.html JarURLConnection (Java Platform SE 6)]を参考にして「パス」を「エントリ」に変更してみました。 -- [[aterai]] &new{2008-02-15 (金) 18:04:14};
- `ant`などでコンパイルして、修正した`run.bat`で実行

この場合、`src.zip`に元々入っていた`適当な場所/test.png`ではなく、`file:/C:/temp/example/test.png`という`URL`が`getResource`で取得できます。

* 参考リンク [#reference]
- [https://docs.oracle.com/javase/jp/8/docs/technotes/guides/lang/resources.html 位置に依存しない方法でのリソースへのアクセス]
- [https://docs.oracle.com/javase/tutorial/uiswing/components/icon.html#getresource Loading Images Using getResource]

* コメント [#comment]
#comment
- 「クラスパスからのパス」などの意味が分かり辛いので、[https://docs.oracle.com/javase/jp/8/docs/api/java/net/JarURLConnection.html JarURLConnection (Java Platform SE 8)]を参考にして「パス」を「エントリ」に変更してみました。 -- &user(aterai); &new{2008-02-15 (金) 18:04:14};
- `.jar`ファイルのクラスで -- &user(kind); &new{2012-03-02 (金) 14:04:06};
-- 見落としてました。最近なんか重いので途切れてしまったのでしょうか。 -- &user(aterai); &new{2012-03-05 (月) 16:26:35};

#comment