web-dev-qa-db-de.com

Wie kann ich eine Ressource "Ordner" aus meiner jar-Datei bekommen?

Ich habe einen Ressourcenordner/-paket im Stammverzeichnis meines Projekts. Ich möchte eine bestimmte Datei "nicht" laden. Wenn ich eine bestimmte Datei laden wollte, würde ich class.getResourceAsStream verwenden und es würde mir gut gehen !! Was ich eigentlich tun möchte, ist, einen "Ordner" im Ressourcenordner zu laden, die Dateien in diesem Ordner in einer Schleife zu durchlaufen und einen Stream zu jeder Datei zu erhalten und den Inhalt zu lesen ... Was soll ich machen? Gibt es eine Möglichkeit, eine Liste der Dateien in einem Ordner in Ihrer JAR-Datei abzurufen? Beachten Sie, dass die JAR-Datei mit den Ressourcen dieselbe JAR-Datei ist, von der der Code ausgeführt wird ...

Danke im Voraus...

110
Mostafa Zeinali

Zum Schluss habe ich die Lösung gefunden:

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

Der zweite Block funktioniert nur, wenn Sie die Anwendung unter IDE ausführen (nicht mit der JAR-Datei). Sie können sie entfernen, wenn Sie das nicht mögen.

102
user1079877

Versuche Folgendes.
Machen Sie den Ressourcenpfad "<PathRelativeToThisClassFile>/<ResourceDirectory>" E.g. Wenn Ihr Klassenpfad com.abc.package.MyClass lautet und sich Ihre Ressourcendateien innerhalb von src/com/abc/package/resources/befinden:

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

Sie können auch verwenden 

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

Ich weiß, das ist vor vielen Jahren. Aber nur, wenn andere Leute auf dieses Thema stoßen. Was Sie tun könnten, ist, die getResourceAsStream()-Methode mit dem Verzeichnispfad zu verwenden, und der Eingabestrom enthält alle Dateinamen aus diesem Verzeichnis. Danach können Sie den Verzeichnispfad mit jedem Dateinamen zusammenführen und für jede Datei in einer Schleife getResourceAsStream aufrufen.

6
Cheng Lin

Ich hatte das gleiche Problem in den Händen, als ich versuchte, einige Hadoop-Konfigurationen von Ressourcen zu laden, die in das Gefäß gepackt waren ... sowohl auf der IDE als auch auf dem Gefäß (Release-Version).

Ich fand Java.nio.file.DirectoryStream am besten, um Verzeichnisinhalte sowohl über das lokale Dateisystem als auch über jar zu durchlaufen.

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
SQL.injection

Der folgende Code gibt den gewünschten "Ordner" als Pfad zurück, unabhängig davon, ob er sich in einem Glas befindet oder nicht. 

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

Benötigt Java 7+.

2
hummingV

Eine andere Lösung können Sie mit ResourceLoader wie folgt ausführen:

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
Qy Zuo

Einfach ... benutze OSGi. In OSGi können Sie die Einträge Ihres Bundles mit findEntries und findPaths durchlaufen.

0
Peter Kriens