Java Jar-файл: использовать ошибки ресурсов: URI не является иерархическим
я развернул свое приложение в файл jar. Когда мне нужно скопировать данные из одного файла ресурса за пределы файла 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
//....
}
5 ответов
вы не можете сделать это
File src = new File(resourceUrl.toURI()); //ERROR HERE
это не файл! При запуске из ide у вас нет ошибок, потому что вы не запускаете файл jar. В IDE классы и ресурсы извлекаются в файловой системе.
но вы можете открыть InputStream
таким образом:
InputStream in = Model.class.getClassLoader().getResourceAsStream("/data.sav");
удалить "/resource"
. Как правило, IDEs разделяет классы и ресурсы файловой системы. Но когда кувшин создается, они складываются вместе. Итак, уровень папки "/resource"
используется только для разделение классов и ресурсов.
когда вы получаете ресурс из classloader, вы должны указать путь, который ресурс имеет внутри jar, то есть реальную иерархию пакетов.
Если по какой-то причине вам действительно нужно создать java.io.File
объект, чтобы указать на ресурс внутри файла Jar, ответ здесь:https://stackoverflow.com/a/27149287/155167
File f = new File(getClass().getResource("/MyResource").toExternalForm());
вот решение для разработчиков Eclipse RCP / Plugin:
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)
, причина, когда плагин упакован в банку, это заставит Eclipse создать распакованную версию во временном месте, чтобы к объекту можно было получить доступ с помощью файла. Например, я предполагаю, что у Ларса Фогеля есть ошибка в его статье -http://blog.vogella.com/2010/07/06/reading-resources-from-plugin/
пока я сам наткнулся на эту проблему, я хотел бы добавить еще один вариант (в противном случае идеальное объяснение от @dash1e):
экспортируйте плагин как папку (не банку), добавив:
Eclipse-BundleShape: dir
на MANIFEST.MF
.
по крайней мере, при экспорте приложения RCP с помощью мастера экспорта (на основе *.product
) файл это уважается и будет создавать папку.
в дополнение к общим ответам вы можете получить "URI не является иерархическим" из Unitils библиотека пытается загрузить dataset С . Это может произойти, когда вы храните наборы данных в одном подмодуле maven, но фактические тесты в другом.
есть даже ошибка UNI-197 подано.