如何从我的jar文件中获取资源“文件夹”?

时间:2012-06-13 10:19:40

标签: java list resources directory

我的项目根目录中有一个资源文件夹/包,我“不”想要加载某个文件。如果我想加载某个文件,我会使用class.getResourceAsStream,我会没事的!我真正想做的是在资源文件夹中加载一个“文件夹”,循环该文件夹内的文件,并获取每个文件的流并读入内容...假设在运行时之前未确定文件名... 我该怎么办?有没有办法在jar文件中获取文件夹中的文件列表? 请注意,带有资源的Jar文件与运行代码的jar文件相同...

提前致谢...

12 个答案:

答案 0 :(得分:104)

最后,我找到了解决方案:

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文件),如果不喜欢,可以将其删除。

答案 1 :(得分:15)

请尝试以下方法 创建资源路径"<PathRelativeToThisClassFile>/<ResourceDirectory>"例如。如果你的类路径是com.abc.package.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/");

答案 2 :(得分:7)

我知道这是很多年前的事了。但只是为了其他人遇到这个话题。 你可以做的是使用getResourceAsStream()方法与目录路径,输入流将具有该目录中的所有文件名。之后,您可以使用每个文件名连接dir路径,并为循环中的每个文件调用getResourceAsStream。

答案 3 :(得分:5)

当我尝试从jar中包装的资源中加载一些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());
    }
}

答案 4 :(得分:3)

以下代码返回所需的&#34;文件夹&#34;作为路径,无论它是否在罐子里面。

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

答案 5 :(得分:1)

另一种解决方案,您可以使用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())
}

答案 6 :(得分:0)

简单......使用OSGi。在OSGi中,您可以使用findEntries和findPaths迭代Bundle的条目。

答案 7 :(得分:0)

下面的代码从自定义资源目录中获取 .yaml 文件。

{{1}}

答案 8 :(得分:0)

如果您使用的是 Spring,您可以使用 org.springframework.core.io.support.PathMatchingResourcePatternResolver 并处理 Resource 对象而不是文件。这在 Jar 文件内部和外部运行时都有效。

PathMatchingResourcePatternResolver r = new PathMatchingResourcePatternResolver();
Resource[] resources = r.getResources("/myfolder/*");

然后您可以使用 getInputStream 和来自 getFilename 的文件名访问数据。

请注意,如果您在从 Jar 运行时尝试使用 getFile,它仍然会失败。

答案 9 :(得分:-1)

在我的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);

答案 10 :(得分:-1)

正如其他答案所指出的那样,一旦资源在jar文件中,事情变得非常难看。在我们的例子中,这个解决方案:

https://stackoverflow.com/a/13227570/516188

在测试中运行良好(因为在运行测试时,代码未打包在jar文件中),但在应用程序实际正常运行时不起作用。所以我所做的就是......我对应用程序中的文件列表进行了硬编码,但我有一个测试,它从磁盘读取实际列表(可以在测试中使用它),如果实际的话,则会失败列表与应用返回的列表不匹配。

这样我在我的应用程序中有简单的代码(没有技巧),我确定我没有忘记在列表中添加新条目,这要归功于测试

答案 11 :(得分:-22)

link告诉你如何。

神奇的是getResourceAsStream()方法:

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