Как получить путь к ресурсу в файле Java JAR
Я пытаюсь получить путь к ресурсу, но мне не повезло.
это работает (как в IDE, так и с JAR), но таким образом я не могу получить путь к файлу, только содержимое файла:
ClassLoader classLoader = getClass().getClassLoader();
PrintInputStream(classLoader.getResourceAsStream("config/netclient.p"));
Если я сделаю это:
ClassLoader classLoader = getClass().getClassLoader();
File file = new File(classLoader.getResource("config/netclient.p").getFile());
результат:
java.io.FileNotFoundException: file:/path/to/jarfile/bot.jar!/config/netclient.p (No such file or directory)
есть ли способ получить путь к файлу ресурса?
14 ответов:
это умышленное. Содержимое "файла" может быть недоступно в виде файла. Помните, вы имеете дело с классами и ресурсами, которые могут быть частью файла jar или другого вида ресурса. Загрузчик классов не должен предоставлять дескриптор файла для ресурса, например файл jar не может быть развернут в отдельные файлы в файловой системе.
все, что вы можете сделать, получив java.io. File может быть сделано путем копирования потока во временный файл и делать то же самое, если java.io.файл абсолютно необходим.
при загрузке ресурса убедитесь, что вы заметили разницу между:
getClass().getClassLoader().getResource("com/myorg/foo.jpg") //relative pathи
getClass().getResource("/com/myorg/foo.jpg")); //note the slash at the beginningЯ думаю, эта путаница вызывает большинство проблем при загрузке ресурса.
кроме того, когда вы загружаете изображение, его проще использовать
getResourceAsStream():BufferedImage image = ImageIO.read(getClass().getResourceAsStream("/com/myorg/foo.jpg"));когда вам действительно нужно загрузить файл (без изображения) из архива JAR, вы можете попробовать это:
File file = null; String resource = "/com/myorg/foo.xml"; URL res = getClass().getResource(resource); if (res.toString().startsWith("jar:")) { try { InputStream input = getClass().getResourceAsStream(resource); file = File.createTempFile("tempfile", ".tmp"); OutputStream out = new FileOutputStream(file); int read; byte[] bytes = new byte[1024]; while ((read = input.read(bytes)) != -1) { out.write(bytes, 0, read); } file.deleteOnExit(); } catch (IOException ex) { Exceptions.printStackTrace(ex); } } else { //this will probably work in your IDE, but not from a JAR file = new File(res.getFile()); } if (file != null && !file.exists()) { throw new RuntimeException("Error: File " + file + " not found!"); }
ответ на одну строку -
String path = this.getClass().getClassLoader().getResource(<resourceFileName>).toExternalForm()в принципе
getResourceметод дает URL. Из этого URL-адреса вы можете извлечь путь, вызвавtoExternalForm()ссылки:
Я провел некоторое время возиться с этой проблемой, потому что ни одно решение я не нашел на самом деле работал, как ни странно! Рабочий каталог часто не является каталогом JAR, особенно если JAR (или любая программа, если на то пошло) запускается из меню Пуск под Windows. Так вот что я сделал, и это работает .класс файлы, которые запускаются из-за пределов флягу так же хорошо, как он работает за банку. (Я только протестировал его под Windows 7.)
try { //Attempt to get the path of the actual JAR file, because the working directory is frequently not where the file is. //Example: file:/D:/all/Java/TitanWaterworks/TitanWaterworks-en.jar!/TitanWaterworks.class //Another example: /D:/all/Java/TitanWaterworks/TitanWaterworks.class PROGRAM_DIRECTORY = getClass().getClassLoader().getResource("TitanWaterworks.class").getPath(); // Gets the path of the class or jar. //Find the last ! and cut it off at that location. If this isn't being run from a jar, there is no !, so it'll cause an exception, which is fine. try { PROGRAM_DIRECTORY = PROGRAM_DIRECTORY.substring(0, PROGRAM_DIRECTORY.lastIndexOf('!')); } catch (Exception e) { } //Find the last / and cut it off at that location. PROGRAM_DIRECTORY = PROGRAM_DIRECTORY.substring(0, PROGRAM_DIRECTORY.lastIndexOf('/') + 1); //If it starts with /, cut it off. if (PROGRAM_DIRECTORY.startsWith("/")) PROGRAM_DIRECTORY = PROGRAM_DIRECTORY.substring(1, PROGRAM_DIRECTORY.length()); //If it starts with file:/, cut that off, too. if (PROGRAM_DIRECTORY.startsWith("file:/")) PROGRAM_DIRECTORY = PROGRAM_DIRECTORY.substring(6, PROGRAM_DIRECTORY.length()); } catch (Exception e) { PROGRAM_DIRECTORY = ""; //Current working directory instead. }
Если
netclient.pнаходится внутри файла JAR, у него не будет пути, потому что этот файл находится внутри другого файла. в этом случае лучший путь, который вы можете иметь, действительноfile:/path/to/jarfile/bot.jar!/config/netclient.p.
вам нужно понять путь в файле jar.
Просто обратитесь к нему относительно. Так что если у вас есть файл (файл myfile.txt), расположенный в foo.баночка под\src\main\resourcesкаталог (стиль maven). Вы бы назвали его так:src/main/resources/myfile.txtЕсли вы сбрасываете свою банку с помощью
jar -tvf myjar.jarвы увидите вывод и относительный путь в файле jar, а также использовать прямые косые черты.
файл-это абстракция для файла в файловой системе, и файловые системы ничего не знают о том, что такое содержимое JAR.
попробуйте с URI, я думаю, что есть jar:// протокол, который может быть полезен для ваших целей.
Это тот же код от пользователя Tombart с потоком flush и close, чтобы избежать неполной временной копии содержимого файла из ресурса jar и иметь уникальные имена временных файлов.
File file = null; String resource = "/view/Trial_main.html" ; URL res = getClass().getResource(resource); if (res.toString().startsWith("jar:")) { try { InputStream input = getClass().getResourceAsStream(resource); file = File.createTempFile(new Date().getTime()+"", ".html"); OutputStream out = new FileOutputStream(file); int read; byte[] bytes = new byte[1024]; while ((read = input.read(bytes)) != -1) { out.write(bytes, 0, read); } out.flush(); out.close(); input.close(); file.deleteOnExit(); } catch (IOException ex) { ex.printStackTrace(); } } else { //this will probably work in your IDE, but not from a JAR file = new File(res.getFile()); }
в моем случае, я использовал объект URL вместо пути.
File
File file = new File("my_path"); URL url = file.toURI().toURL();ресурс в classpath с помощью classloader
URL url = MyClass.class.getClassLoader().getResource("resource_name")когда мне нужно прочитать содержимое, я могу использовать следующий код:
InputStream stream = url.openStream();и вы можете получить доступ к содержимому с помощью InputStream.
это, как было сказано, не оптимальный способ загрузки ресурсов, но если вы абсолютно должны иметь
java.io.Fileссылка, а затем попробуйте следующее:URL url = null; try { URL baseUrl = YourClass.class.getResource("."); if (baseUrl != null) { url = new URL(baseUrl, "yourfilename.ext"); } else { url = YourClass.class.getResource("yourfilename.ext"); } } catch (MalformedURLException e) { // Do something appropriate }это дает вам
java.net.URLи его можно использовать вjava.io.Fileконструктор.
private static final String FILE_LOCATION = "com/input/file/somefile.txt"; //Method Body InputStream invalidCharacterInputStream = URLClassLoader.getSystemResourceAsStream(FILE_LOCATION);это
getSystemResourceAsStreamэто лучший вариант. Получая inputstream, а не файл или URL-адрес, работает в файле JAR и как автономный.
когда в файле jar ресурс находится абсолютно в иерархии пакетов (а не в иерархии файловой системы). Так что если у вас есть класс com.образец.Сладкая загрузка ресурса с именем"./неисполнение.conf "тогда имя ресурса указывается как" /com/example / default.конф".
но если это в банке, то это не файл ...
В папке ressources (java / main / resources) вашего jar добавьте свой файл (мы предполагаем, что вы добавили xml-файл с именем импорт.xml), после чего вы вводите
ResourceLoaderЕсли вы используете весна, как ниже@Autowired private ResourceLoader resourceLoader;внутри функции тура напишите ниже код для загрузки файла:
Resource resource = resourceLoader.getResource("classpath:imports.xml"); try{ File file; file = resource.getFile();//will load the file ... }catch(IOException e){e.printStackTrace();}
Comments