Как я могу получить ресурс "папка" из моего файла jar?
У меня есть папка/пакет ресурсов в корне моего проекта, я "не хочу" загружать определенный файл. Если бы я хотел загрузить определенный файл, я бы использовал класс.getResourceAsStream и я были бы в порядке!! То, что я на самом деле хочу сделать, это загрузить "папку" в папку ресурсов, зациклиться на файлах внутри этой папки и получить поток в каждый файл и прочитать содержимое... Предположим, что имена файлов не определены до выполнения... Что же мне делать? Есть ли способ получить список файлы внутри папки в файле jar? Обратите внимание, что файл Jar с ресурсами-это тот же файл jar, из которого выполняется код...
спасибо заранее...
10 ответов:
наконец, я нашел решение:
final String path = "sample/folder"; final File jarFile = new File(getClass().getProtectionDomain().getCodeSource().getLocation().getPath()); if(jarFile.isFile()) { // Run with JAR file final JarFile jar = new JarFile(jarFile); final Enumeration<JarEntry> entries = jar.entries(); //gives ALL entries in jar while(entries.hasMoreElements()) { final String name = entries.nextElement().getName(); if (name.startsWith(path + "/")) { //filter according to the path System.out.println(name); } } jar.close(); } else { // Run with IDE final URL url = Launcher.class.getResource("/" + path); if (url != null) { try { final File apps = new File(url.toURI()); for (File app : apps.listFiles()) { System.out.println(app); } } catch (URISyntaxException ex) { // never happens } } }
второй блок просто работает, когда вы запускаете приложение на IDE (не с файлом jar), вы можете удалить его, если вам это не нравится.
попробуйте следующее.
Сделайте путь к ресурсу"<PathRelativeToThisClassFile>/<ResourceDirectory>"
например, если ваш путь к классу com.азбука.пакет.MyClass и ваши файлы ресурсов находятся в пределах src / com/abc/package/resources/:URL url = MyClass.class.getResource("resources/"); if (url == null) { // error - missing folder } else { File dir = new File(url.toURI()); for (File nextFile : dir.listFiles()) { // Do something with nextFile } }
вы также можете использовать
URL url = MyClass.class.getResource("/com/abc/package/resources/");
Я знаю, что это много лет назад . Но как раз для других людей попадается эта тема. Что вы могли бы сделать, это использовать
getResourceAsStream()
метод с путем к каталогу, и входной поток будет иметь все имена файлов из этого каталога. После этого вы можете связать путь dir с каждым именем файла и вызвать getResourceAsStream для каждого файла в цикле.
у меня была такая же проблема на руках, когда я пытался загрузить некоторые конфигурации hadoop из ресурсов, упакованных в банку... как на IDE, так и на jar (версия выпуска).
нашел
java.nio.file.DirectoryStream
для работы лучше всего перебирать содержимое каталога как по локальной файловой системе, так и по jar.String fooFolder = "/foo/folder"; .... ClassLoader classLoader = foofClass.class.getClassLoader(); try { uri = classLoader.getResource(fooFolder).toURI(); } catch (URISyntaxException e) { throw new FooException(e.getMessage()); } catch (NullPointerException e){ throw new FooException(e.getMessage()); } if(uri == null){ throw new FooException("something is wrong directory or files missing"); } /** i want to know if i am inside the jar or working on the IDE*/ if(uri.getScheme().contains("jar")){ /** jar case */ try{ URL jar = FooClass.class.getProtectionDomain().getCodeSource().getLocation(); //jar.toString() begins with file: //i want to trim it out... Path jarFile = Paths.get(jar.toString().substring("file:".length())); FileSystem fs = FileSystems.newFileSystem(jarFile, null); DirectoryStream<Path> directoryStream = Files.newDirectoryStream(fs.getPath(fooFolder)); for(Path p: directoryStream){ InputStream is = FooClass.class.getResourceAsStream(p.toString()) ; performFooOverInputStream(is); /** your logic here **/ } }catch(IOException e) { throw new FooException(e.getMessage()); } } else{ /** IDE case */ Path path = Paths.get(uri); try { DirectoryStream<Path> directoryStream = Files.newDirectoryStream(path); for(Path p : directoryStream){ InputStream is = new FileInputStream(p.toFile()); performFooOverInputStream(is); } } catch (IOException _e) { throw new FooException(_e.getMessage()); } }
следующий код возвращает нужную "папку" в качестве пути независимо от того, находится ли она внутри банки или нет.
private Path getFolderPath() throws URISyntaxException, IOException { URI uri = getClass().getClassLoader().getResource("folder").toURI(); if ("jar".equals(uri.getScheme())) { FileSystem fileSystem = FileSystems.newFileSystem(uri, Collections.emptyMap(), null); return fileSystem.getPath("path/to/folder/inside/jar"); } else { return Paths.get(uri); } }
требуется java 7+.
другое решение, вы можете сделать это с помощью
ResourceLoader
такой:import org.springframework.core.io.Resource; import org.apache.commons.io.FileUtils; @Autowire private ResourceLoader resourceLoader; ... Resource resource = resourceLoader.getResource("classpath:/path/to/you/dir"); File file = resource.getFile(); Iterator<File> fi = FileUtils.iterateFiles(file, null, true); while(fi.hasNext()) { load(fi.next()) }
простой ... использование OSGi для. В OSGi вы можете перебирать записи вашего пакета с помощью findEntries и findPaths.
внутри моего файла jar у меня была папка с именем Upload, в этой папке было три других текстовых файла внутри нее, и мне нужно было иметь точно такую же папку и файлы за пределами файла jar, я использовал код ниже:
URL inputUrl = getClass().getResource("/upload/blabla1.txt"); File dest1 = new File("upload/blabla1.txt"); FileUtils.copyURLToFile(inputUrl, dest1); URL inputUrl2 = getClass().getResource("/upload/blabla2.txt"); File dest2 = new File("upload/blabla2.txt"); FileUtils.copyURLToFile(inputUrl2, dest2); URL inputUrl3 = getClass().getResource("/upload/blabla3.txt"); File dest3 = new File("upload/Bblabla3.txt"); FileUtils.copyURLToFile(inputUrl3, dest3);
Как указывают другие ответы, как только ресурсы находятся внутри файла jar, все становится действительно уродливым. В нашем случае, это решение:
https://stackoverflow.com/a/13227570/516188
работает очень хорошо в тестах (так как при запуске тестов код не упакованные в jar-файл), но не работает, когда приложение на самом деле работает нормально. Так что я сделал вот что... Я жестко задать список файлов в приложении, но у меня есть тест, который считывает реальный список с диска (может сделать это, так как это работает в тестах) и терпит неудачу, если фактический список не совпадает со списком, который возвращает приложение.
таким образом, у меня есть простой код в моем приложении (без трюков), и Я уверен, что не забыл добавить новую запись в список благодаря тесту.
этой ссылке расскажет вам, как.
магия-это метод getResourceAsStream ():
InputStream is = this.getClass().getClassLoader().getResourceAsStream("yourpackage/mypackage/myfile.xml")