web-dev-qa-db-ja.com

Java Jarファイル:リソースエラーを使用:URIは階層的ではありません

アプリをjarファイルにデプロイしました。リソースの1つのファイルからjarファイルの外部にデータをコピーする必要がある場合、次のコードを実行します。

URL resourceUrl = getClass().getResource("/resource/data.sav");
File src = new File(resourceUrl.toURI()); //ERROR HERE
File dst = new File(CurrentPath()+"data.sav");  //CurrentPath: path of jar file don't include jar file name
FileInputStream in = new FileInputStream(src);
FileOutputStream out = new FileOutputStream(dst);
 // some excute code here

私が遭遇したエラーは:URI is not hierarchical。 IDEで実行すると、このエラーは発生しません。

StackOverFlowの他の投稿の助けとして上記のコードを変更した場合:

InputStream in = Model.class.getClassLoader().getResourceAsStream("/resource/data.sav");
File dst = new File(CurrentPath() + "data.sav");
FileOutputStream out = new FileOutputStream(dst);
//....
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) { //NULL POINTER EXCEPTION
  //....
}
54
hqt

これはできません

File src = new File(resourceUrl.toURI()); //ERROR HERE

ファイルではありません! IDEから実行する場合、jarファイルを実行しないため、エラーは発生しません。 IDE=でクラスとリソースがファイルシステムに抽出されます。

ただし、次の方法でInputStreamを開くことができます。

    InputStream in = Model.class.getClassLoader().getResourceAsStream("/data.sav");

削除する "/resource"。通常、IDEはファイルシステムクラスとリソースを分離します。しかし、jarが作成されると、それらはすべてまとめられます。フォルダーレベル"/resource"は、クラスとリソースの分離にのみ使用されます。

クラスローダーからリソースを取得する場合、jar内のリソースのパス、つまり実際のパッケージ階層を指定する必要があります。

90
dash1e

何らかの理由でJava.io.Fileオブジェクトを作成してJarファイル内のリソースを指す必要がある場合、答えは次のとおりです。 https://stackoverflow.com/a/27149287/155167

File f = new File(getClass().getResource("/MyResource").toExternalForm());
13
Mario

Eclipse RCP /プラグイン開発者向けのソリューションは次のとおりです。

_Bundle bundle = Platform.getBundle("resource_from_some_plugin");
URL fileURL = bundle.getEntry("files/test.txt");
File file = null;
try {
   URL resolvedFileURL = FileLocator.toFileURL(fileURL);

   // We need to use the 3-arg constructor of URI in order to properly escape file system chars
   URI resolvedURI = new URI(resolvedFileURL.getProtocol(), resolvedFileURL.getPath(), null);
   File file = new File(resolvedURI);
} catch (URISyntaxException e1) {
    e1.printStackTrace();
} catch (IOException e1) {
    e1.printStackTrace();
}
_

FileLocator.toFileURL(fileURL)ではなくresolve(fileURL)を使用することが非常に重要です。これは、プラグインをjarにパックすると、Eclipseが一時的な場所にアンパックバージョンを作成し、オブジェクトがFileを使用してアクセスします。たとえば、Lars Vogelの記事に誤りがあると思います- http://blog.vogella.com/2010/07/06/reading-resources-from-plugin/

8
Ilya Buziuk

以前にも同様の問題が発生したため、コードを使用しました。

new File(new URI(url.toString().replace(" ","%20")).getSchemeSpecificPart());

コードの代わりに:

new File(new URI(url.toURI())

問題を解決するため

0
Yukai Tang

一般的な回答に加えて、Unitilsライブラリから(URIは階層的ではありません)を取得でき、dataset.jarファイル。 1つのMavenサブモジュールにデータセットを保持し、別のMavenサブモジュールに実際のテストを保持すると発生する場合があります。

さらに バグUNI-197 が提出されています。

0
jediz

私がこの問題に自分でつまずいた間に、別のオプションを追加したいと思います(@ dash1eからの完璧な説明に):

以下を追加して、プラグインを(jarではなく)フォルダーとしてエクスポートします。

Eclipse-BundleShape: dir

あなたのMANIFEST.MF

少なくとも、エクスポートウィザードを使用してRCPアプリをエクスポートする場合(*.product)これは尊重され、フォルダーを作成します。

0
Jens