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

时间:2023-01-07 00:33:48

I have a resources folder/package in the root of my project, I "don't" want to load a certain File. If I wanted to load a certain File, I would use class.getResourceAsStream and I would be fine!! What I actually want to do is to load a "Folder" within the resources folder, loop on the Files inside that Folder and get a Stream to each file and read in the content... Assume that the File names are not determined before runtime... What should I do? Is there a way to get a list of the files inside a Folder in your jar File? Notice that the Jar file with the resources is the same jar file from which the code is being run...

我在项目的根目录中有一个资源文件夹/包,我不想加载某个文件。如果我想加载某个文件,我会使用class。getresourcesstream and I would be fine!!我真正想做的是在resources文件夹中加载一个“文件夹”,循环该文件夹中的文件,获取每个文件的流,并在内容中读取……假设在运行之前没有确定文件名……我应该做什么?是否有一种方法可以在jar文件的文件夹中获取文件列表?注意,带有资源的Jar文件与运行代码的Jar文件相同……

Thanks in advance...

提前谢谢…

10 个解决方案

#1


96  

Finally, I found the solution:

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

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
        }
    }
}

The second block just work when you run the application on IDE (not with jar file), You can remove it if you don't like that.

当您在IDE上运行应用程序(不是使用jar文件)时,第二个块就会工作,如果您不喜欢,可以删除它。

#2


15  

Try the following.
Make the resource path "<PathRelativeToThisClassFile>/<ResourceDirectory>" E.g. if your class path is com.abc.package.MyClass and your resoure files are within src/com/abc/package/resources/:

试试下面的。使资源路径“ / ”,例如,如果您的类路径是com.abc.package。MyClass和您的resources文件位于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
    }
}

You can also use

您还可以使用

URL url = MyClass.class.getResource("/com/abc/package/resources/");

#3


5  

I know this is many years ago . But just for other people come across this topic. What you could do is to use getResourceAsStream() method with the directory path, and the input Stream will have all the files name from that dir. After that you can concat the dir path with each file name and call getResourceAsStream for each file in a loop.

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

#4


4  

I had the same problem at hands while i was attempting to load some hadoop configurations from resources packed in the jar... on both the IDE and on jar (release version).

当我试图从jar中打包的资源中加载一些hadoop配置时,我遇到了同样的问题。在IDE和jar(发布版本)上。

I found java.nio.file.DirectoryStream to work the best to iterate over directory contents over both local filesystem and 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());
    }
}

#5


1  

Simple ... use OSGi. In OSGi you can iterate over your Bundle's entries with findEntries and findPaths.

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

#6


1  

Another solution, you can do it using ResourceLoader like this:

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

#7


1  

The following code returns the wanted "folder" as Path regardless of if it is inside a jar or not.

下面的代码返回想要的“文件夹”作为路径,不管它是否在jar中。

  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);
    }
  }

Requires java 7+.

需要java 7 +。

#8


0  

Inside my jar file I had a folder called Upload, this folder had three other text files inside it and I needed to have an exactly the same folder and files outside of the jar file, I used the code below:

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

#9


0  

As the other answers point out, once the resources are inside a jar file, things get really ugly. In our case, this solution:

正如其他答案所指出的,一旦资源在jar文件中,事情就会变得非常糟糕。在我们的案例中,这个解决方案是:

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

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

works very well in the tests (since when the tests are run the code is not packed in a jar file), but doesn't work when the app actually runs normally. So what I've done is... I hardcode the list of the files in the app, but I have a test which reads the actual list from disk (can do it since that works in tests) and fails if the actual list doesn't match with the list the app returns.

在测试中工作得很好(因为当运行测试时,代码没有被打包到jar文件中),但是当应用程序实际正常运行时,它就不能工作了。所以我所做的是…我硬编码了应用程序中的文件列表,但是我有一个测试,它从磁盘读取实际的列表(可以这样做,因为在测试中它是有效的),如果实际的列表与应用程序返回的列表不匹配,则失败。

That way I have simple code in my app (no tricks), and I'm sure I didn't forget to add a new entry in the list thanks to the test.

这样,我的应用程序中就有了简单的代码(没有诀窍),而且我确信由于测试,我不会忘记在列表中添加一个新条目。

#10


-20  

This link tells you how.

这个链接告诉你怎么做。

The magic is the getResourceAsStream() method :

神奇的是getresourcestream()方法:

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

#1


96  

Finally, I found the solution:

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

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
        }
    }
}

The second block just work when you run the application on IDE (not with jar file), You can remove it if you don't like that.

当您在IDE上运行应用程序(不是使用jar文件)时,第二个块就会工作,如果您不喜欢,可以删除它。

#2


15  

Try the following.
Make the resource path "<PathRelativeToThisClassFile>/<ResourceDirectory>" E.g. if your class path is com.abc.package.MyClass and your resoure files are within src/com/abc/package/resources/:

试试下面的。使资源路径“ / ”,例如,如果您的类路径是com.abc.package。MyClass和您的resources文件位于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
    }
}

You can also use

您还可以使用

URL url = MyClass.class.getResource("/com/abc/package/resources/");

#3


5  

I know this is many years ago . But just for other people come across this topic. What you could do is to use getResourceAsStream() method with the directory path, and the input Stream will have all the files name from that dir. After that you can concat the dir path with each file name and call getResourceAsStream for each file in a loop.

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

#4


4  

I had the same problem at hands while i was attempting to load some hadoop configurations from resources packed in the jar... on both the IDE and on jar (release version).

当我试图从jar中打包的资源中加载一些hadoop配置时,我遇到了同样的问题。在IDE和jar(发布版本)上。

I found java.nio.file.DirectoryStream to work the best to iterate over directory contents over both local filesystem and 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());
    }
}

#5


1  

Simple ... use OSGi. In OSGi you can iterate over your Bundle's entries with findEntries and findPaths.

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

#6


1  

Another solution, you can do it using ResourceLoader like this:

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

#7


1  

The following code returns the wanted "folder" as Path regardless of if it is inside a jar or not.

下面的代码返回想要的“文件夹”作为路径,不管它是否在jar中。

  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);
    }
  }

Requires java 7+.

需要java 7 +。

#8


0  

Inside my jar file I had a folder called Upload, this folder had three other text files inside it and I needed to have an exactly the same folder and files outside of the jar file, I used the code below:

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

#9


0  

As the other answers point out, once the resources are inside a jar file, things get really ugly. In our case, this solution:

正如其他答案所指出的,一旦资源在jar文件中,事情就会变得非常糟糕。在我们的案例中,这个解决方案是:

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

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

works very well in the tests (since when the tests are run the code is not packed in a jar file), but doesn't work when the app actually runs normally. So what I've done is... I hardcode the list of the files in the app, but I have a test which reads the actual list from disk (can do it since that works in tests) and fails if the actual list doesn't match with the list the app returns.

在测试中工作得很好(因为当运行测试时,代码没有被打包到jar文件中),但是当应用程序实际正常运行时,它就不能工作了。所以我所做的是…我硬编码了应用程序中的文件列表,但是我有一个测试,它从磁盘读取实际的列表(可以这样做,因为在测试中它是有效的),如果实际的列表与应用程序返回的列表不匹配,则失败。

That way I have simple code in my app (no tricks), and I'm sure I didn't forget to add a new entry in the list thanks to the test.

这样,我的应用程序中就有了简单的代码(没有诀窍),而且我确信由于测试,我不会忘记在列表中添加一个新条目。

#10


-20  

This link tells you how.

这个链接告诉你怎么做。

The magic is the getResourceAsStream() method :

神奇的是getresourcestream()方法:

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