3
votes

Répertoriez les noms de tous les sous-répertoires dans le dossier de ressources d'un JAR

J'ai empaqueté mon projet Spring Boot dans un JAR à l'aide de maven. Je souhaite lire les noms de tous les répertoires sous "static / foo" dans le dossier resources.

J'ai essayé ce qui suit en utilisant la bibliothèque Apache Commons:

String fooPath = "static/foo";
URL url = Thread.currentThread().getContextClassLoader().getResource(fooPath);

// Not running from JAR
if (url.getProtocol().equals("file"))
{
    try {
        // Get list of subdirectories' folder names
        List<String> fooFolders = IOUtils.readLines(this.getClass().getClassLoader().getResourceAsStream(fooPath), Charsets.UTF_8);

        // Loop subdirectories
        for (String fooFolder : fooFolders) {
            // The current subdirectory path
            String fooFolderPath = fooPath + "/" + fooFolder;

            // Loop all files in this subdirectory, if needed
            List<String> fooFiles = IOUtils.readLines(this.getClass().getClassLoader().getResourceAsStream(fooFolderPath), Charsets.UTF_8);

            for (String fooFile : fooFiles) {
                // The updated path of the file
                String fooFilePath = fooFolderPath + "/" + fooFile;

                // Read the file's content
                InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(fooFilePath);
                StringWriter writer = new StringWriter();
                IOUtils.copy(inputStream, writer, Charsets.UTF_8);
                String fileContent = writer.toString();
            }
        }
    }
    catch (IOException e) {
        e.printStackTrace();
    }
}

// Running from JAR
else if (url.getProtocol().equals("jar")) {
    String dirname = fooPath + "/";
    String path = url.getPath();
    String jarPath = path.substring(5, path.indexOf("!"));

    List<String> fooFolders = new ArrayList<String>();
    HashMap<String, List<String>> fooFiles = new HashMap<String, List<String>>();

    try (JarFile jar = new JarFile(URLDecoder.decode(jarPath, StandardCharsets.UTF_8.name()))) {
        Enumeration<JarEntry> entries = jar.entries();
        while (entries.hasMoreElements()) {
            JarEntry entry = entries.nextElement();
            String jarEntryName = entry.getName();

            String updated_dir_name = "BOOT-INF/classes/" + dirname;

            // Only get files that are in the directory we require (fooPath)
            if (jarEntryName.startsWith(updated_dir_name) && !dirname.equals(updated_dir_name)) {

                // Get the resource URL
                URL resourceURL = Thread.currentThread().getContextClassLoader().getResource(jarEntryName);

                // Files only
                if (!jarEntryName.endsWith("/")) {

                    // Split the foo number and the file name
                    String[] split = jarEntryName.split("/");

                    // First level subdirectories inside fooPath
                    // BOOT-INF/classes/static/foo/1/myfile.html
                    // We want to read the folder name "1"
                    String folderName = split[split.length - 2];

                    // If you want to read this file
                    // Read the file's content
                    // InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(resourceURL);
                }
            }
        }
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

UPDATE

Cette solution a fonctionné (légèrement modifiée depuis https://stackoverflow.com/ a / 48190582/1427624 ) en utilisant JarFile

String fooPath = "static/foo/";
List<String> fooFolders = IOUtils.readLines(this.getClass().getClassLoader().getResourceAsStream(fooPath), Charsets.UTF_8);
// The fooFolders list is empty ...


1 commentaires

merci pour la solution en mise à jour.


3 Réponses :


0
votes

Je pense que vous devriez utiliser FileUtils à la place.

En particulier, la méthode listFilesAndDirs avec le filtre DirectoryFileFilter .


1 commentaires

File dir = nouveau fichier (fooPath); List files = (List ) FileUtils.listFilesAndDirs (dir, DirectoryFileFilter.INSTANCE, DirectoryFileFilter.INSTANCE); .... Même problème avec @funkyjelly, il ne lit pas mon chemin comme répertoire



0
votes

Vous pouvez aussi simplement faire ce qui suit:

 File f = new File("static/foo/");
 File[] arr = f.listFiles();
 for (File file : arr) {
     if (file.isDirectory())
        System.out.println(file);
 }


2 commentaires

@ P-S essayez d'utiliser un chemin absolu, par exemple File f = new File ("/ full / path / to / static / foo /");


Je l'ai fait, il retourne null pour la variable arr



0
votes

Des sons comme celui-ci pourraient être résolus par https://stackoverflow.com/a/3923685/7610371

Les bits "de base" de la réponse ci-dessus:

InputStream resourceStream = this.getClass().getClassLoader().getResourceAsStream(fooPath);
BufferedReader br = new BufferedReader(new InputStreamReader(resourceStream)) 
String resource;

while ((resource = br.readLine()) != null) {
    // ... resource is the next filename; you can add it to an array
    // or use it here
}


7 commentaires

Cela ne lève pas d'erreur nullpointerexception, donc je suppose que le chemin est correct, mais resourceStream.available () renvoie 0 (il n'entre pas dans la boucle while) ... Si je change le chemin en un mauvais, j'obtiens une erreur nulle, alors pourquoi le flux est-il vide ...


Pouvez-vous déboguer l'application? Vous pouvez essayer de suivre le code à travers les appels getResource. En outre, vous pouvez vérifier l'ordre utilisé par getResource dans ClassLoader.java pour rechercher la ressource, il se peut qu'il trouve quelque chose avec le même nom dans un endroit différent


Je veux dire lors du débogage dans Eclipse, votre code fonctionne, je peux itérer les noms des sous-répertoires - br.breakline () renvoie les noms des dossiers. Cependant, lorsque je java -jar le projet, br.readLine () retourne null ... C'est en utilisant la même valeur fooPath (également essayé le chemin absolu qui est / BOOT-INF / classes / static / foo) ...


Je ne sais pas si cela fonctionnerait mieux pour vous: smarterco.de/java-load-file-from-classpath-in-spring-boot


Cela fonctionne lorsque je lance dans Eclipse, mais pas lorsque je package tout dans un jar en utilisant maven et que je lance le jar lui-même ...


Oui, tout un tas de variations du chemin ... static / foo, / static / foo, / static / foo /, / BOOT-INF / classes / static / foo /, / BOOT-INF / classes / static / foo , BOOT-INF / classes / static / foo, BOOT-INF / classes / static / foo / ... Cela fonctionne lors de l'exécution d'Eclipse en tant qu'application, mais lorsque je mvn package et java -jar, cela cesse de fonctionner, même Je n'obtiens pas de pointeur nul sur le chemin, mais le flux d'entrée ne lit tout simplement rien


Je l'ai fait fonctionner en filtrant toutes les entrées du fichier JAR. J'ai mis à jour ma question avec la solution.