2012-06-13 2 views
96

У меня есть папка/пакет ресурсов в корне моего проекта, я «не хочу» загружать определенный файл. Если бы я захотел загрузить определенный файл, я бы использовал class.getResourceAsStream, и я был бы в порядке !! То, что я на самом деле хочу сделать, - загрузить «Папка» в папку ресурсов, зациклиться на файлах внутри этой Папки и получить поток для каждого файла и прочитать его содержимое ... Предположим, что имена файлов не определены до времени выполнения ... Что мне делать? Есть ли способ получить список файлов внутри папки в вашем файле jar? Обратите внимание, что файл Jar с ресурсами является та же баночка файл, из которого код бежится ...Как я могу получить ресурс «Папка» из моего файла jar?

Спасибо заранее ...

+1

Это поможет: http://stackoverflow.com/questions/1529611/how-to-write-a-java-program-which-can-extract-a-jar-file-and-store-its-data -in-s –

+0

Также смотрите: http://stackoverflow.com/questions/4764347/extract-and-load-dll-from-jar –

+4

Первый - это извлечение файла jar, который является последним, что я делаю вы хотите попробовать, как если бы ситуация хуже, чем когда-либо хуже! Если я хочу, чтобы файлы были извлечены, я бы просто поместил их в папку установки во время установки! Я хочу получить доступ к ним изнутри банки, и моя причина в том, что если getResourceAsStream может получить доступ к файлу, Java также должна иметь возможность исследовать папки в этой банке, без необходимости ее извлекать !! Но спасибо ... –

ответ

86

Наконец, я нашел решение:

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-файла), вы можете удалить его, если вам не нравится это.

+0

Обновлен правильный ответ.Хотя это не то, что я хотел бы сделать, особенно в коде с 34000 + исходными файлами ... Но это единственное решение. Спасибо. –

+2

FYI, это не работает, если запущено из webstart, потому что getPath возвращает что-то относительно домена сервера. – amos

+0

Не думайте, что это будет работать, если путь находится в банке, даст эту ошибку при преобразовании toURI: java.lang.IllegalArgumentException: URI не является иерархическим – tribbloid

-18

Это link говорит вам, как.

Магия метод getResourceAsStream():

InputStream is = 
this.getClass().getClassLoader().getResourceAsStream("yourpackage/mypackage/myfile.xml") 
+13

Нет, чувак! Я НЕ хочу один файл! Я хочу целую папку, чьи субфайлы не определены до начала выполнения! –

15

Попробуйте следующее.
Сделать путь ресурса "<PathRelativeToThisClassFile>/<ResourceDirectory>" E.g. если ваш класс путь com.abc.package.MyClass и ваши resoure файлы в SRC/COM/а/пакет/ресурсы /:

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/"); 
+16

Спасибо за внимание и время, но это НЕ работает, когда ваша база кода внутри файла .jar и ваши ресурсы также находятся в этом файле .jar. Когда вы находитесь в файле .jar, вы не можете создать File(), и вы также не можете получить URL-адрес для этой папки ... Я лично пришел к нему с миром и просто перечислил каждый файл в XML ... Я не знаю, t думаю, что вы можете сделать это для папки внутри файла jar вообще ... –

+2

Извините, что у вас проблемы. Тем не менее, он действительно работает, когда ваша база кода находится в файле jar, а ваши ресурсы также находятся в этом файле jar. Вы не создаете файл() на диске - вы читаете файл в файле jar в java-памяти. Обратите внимание, что ClassLoader вполне удовлетворен обработкой файла jar, эквивалентного каталогу на диске. Вот подробности из источника: –

+0

Thread.currentThread(). GetContextClassLoader(). GetResource ("Hello.txt"); –

1

Простой ... использование OSGi. В OSGi вы можете перебирать записи своего Bundle с помощью findEntries и findPaths.

+0

На самом деле, это звучит очень хорошая идея, спасибо ... –

+6

Если это связано с OSGI, я бы вряд ли назвал это «простым». Но если вы уже используете OSGI ... да, конечно. Но предлагая перейти на OSGI, чтобы решить эту проблему, кажется, слишком много. – Kris

+0

OSGi также решает многие другие проблемы, и в наши дни очень легко начать работу. См. Учебники OSGi enRoute –

0

Внутри моего файла 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); 
+1

Привет, спасибо за ответ, но, видите ли, вам нужно было знать имя каждого файла внутри этой папки при написании кода; и вы должны были назвать каждый из них явно. То, что я искал, - это метод для итерации файлов внутри папки и получения их имен во время выполнения, поэтому я мог бы добавить ресурсы в папку, не меняя код, зная, что код также обработает их. Спасибо за ваше время. : 3 –

5

Я знаю это много лет назад. Но только для других людей встречают эту тему. Что вы можете сделать, так это использовать метод getResourceAsStream() с пути к каталогу, а входной поток будет иметь все имена файлов из этого каталога. После этого вы можете согласовать путь dir с каждым именем файла и вызвать getResourceAsStream для каждого файла в цикле.

+0

работает как шарм! – Blanka

+0

Это хорошо работает, если вы не планируете разобраться, как выясняется. – Tustin2121

4

У меня была такая же проблема в руках, когда я пытался загрузить некоторые конфигурации хаопов из ресурсов, упакованных в банку ... как на IDE, так и на банке (версия выпуска).

Я нашел 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()); 
    } 
} 
0

Другое решение, вы можете сделать это с помощью 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()) 
} 
1

Следующий код возвращает хотел «папку» в качестве пути, независимо от того, если он находится внутри баночки или нет.

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+.

Смежные вопросы