11
votes

OutofMemory lors de la liste des fichiers dans un répertoire

Lorsque je répertorie les fichiers d'un répertoire comportant 300 000 fichiers avec Java, une mémoire sur la mémoire se produit.

String[] fileNames = file.list();


4 commentaires

La limite de tas de 64 Mo est-elle une condition difficile? Avez-vous également d'autres parties de votre code qui alloue beaucoup d'objets?


64 Mo n'est pas une limite difficile. Cependant, nous souhaitons utiliser Java pour surveiller un dossier dans lequel d'énormes quantités de fichiers sont téléchargées par nos clients. Et nous ne savons pas combien de mémoire suffit.


Une fois que vous les énumérerez tous, qu'allez-vous faire avec le résultat?


Semblable à Stackoverflow.com/Questtions/3139073/...


5 Réponses :


5
votes

Je sais que vous avez dit "avec la limite de tas de 64 m par défaut", mais regardons les faits - vous souhaitez contenir un nombre (potentiellement) grand nombre d'éléments en mémoire, en utilisant les mécanismes mis à votre disposition par Java. Donc, à moins qu'il n'y ait une raison désireuse que vous ne pouvez pas, je dirais que l'augmentation du tas est la voie à suivre.

Voici un lien vers la même discussion à Javaranch: http://www.coderanch.com/t/381939/java-general/java/iteratefover-files-Directory

edit , en réponse au commentaire: La raison pour laquelle j'ai dit qu'il souhaitait détenir un grand nombre d'éléments en mémoire est due, c'est le seul mécanisme Java fournit pour inscrire un répertoire sans utiliser l'interface native sans utiliser l'interface native. ou des mécanismes spécifiques à la plate-forme (et l'OP a dit qu'il voulait "pure java").


3 commentaires

L'appel que James fait des retours un tableau. La question résume si vous pouvez en quelque sorte obtenir l'équivalent d'un itérateur pour les noms dans le répertoire, sans attribuer la matrice complète à la fois. C'est une question raisonnable; Je ne connais pas la réponse du sommet de ma tête.


Vous ne pouvez pas avec l'API Core Java.


Oui, ce que je veux, c'est exactement un fileiterator



1
votes

Avoir 300 000 fichiers dans un DIR n'est pas une bonne idée - les systèmes de fichiers Afaik ne sont pas bons pour avoir de nombreux sous-nœuds dans un seul noeud. Question intéressante, cependant.

EDIT: Ce qui suit n'aide pas, voir les commentaires. Strong> P>

Je pense que vous pouvez utiliser un fichierFilter, rejetez tous les fichiers et les traiter dans le Filtre. P>

        new File("c:/").listFiles( new FileFilter() {
            @Override   public boolean accept(File pathname) {
                processFile();
                return false;
            }
        });


8 commentaires

XFS prend en charge un grand nombre de fichiers dans un seul répertoire. En outre, cette réponse est assez éloignée du sujet.


Vient de vérifier la source pour java.io.file. Il appellera la liste avant de filtrer quand même le problème initial persiste.


Oui, j'aimerais que les gens vérifient au moins les réponses qui "ont l'air juste" avant la modation. Aucune infraction destinée à l'affiche.


Très bien, qui pouvait savoir que les programmeurs JDK ont fait cette façon idiote? Laissant l'anwer ici pour avertir les autres.


Je continue à oublier l'abstraction du système de fichiers JDKS. La méthode de liste réelle qui renvoie une gamme de noms de fichiers String est indigène, il est donc peu d'espoir de pouvoir récupérer une liste partielle de fichiers dans un dir.


FileFilter ne fonctionne pas ici, car le fichier Listfiles (FileFilter Filter) est implémenté en fonction de listfiles ()


@danben - En fait, même si la plupart des systèmes de fichiers "prennent en charge" énormes numéros de fichiers dans un répertoire unique, bon nombre d'entre eux le font d'une manière qui entraîne une recherche de fichiers coûteux. Mettre beaucoup de fichiers dans un répertoire n'est pas une bonne idée.


Désolé que mon libellé soit légèrement éteint. Je vais reformuler - XFS efficacement prend en charge un nombre important de fichiers dans un répertoire unique. Quelle déclaration inutile mon commentaire initial aurait été si je disais simplement que dans un système de fichiers donné, il est possible de mettre un grand nombre de fichiers dans un répertoire.



2
votes

Vous êtes un peu mal de la chance ici. Dans le moins qu'il faudra créer des cordes 300k. Avec une longueur moyenne de 8-10 caractères et 2 octets par caractère de 6 Mo au minimum. Ajoutez une surcharge de pointeur d'objet par chaîne (8 octets) et vous rencontrez dans votre limite de mémoire.

Si vous devez absolument avoir que de nombreux fichiers dans un seul Dir, que je ne recommanderais pas que votre système de fichiers aura des problèmes, votre meilleur choix est d'exécuter un processus natif (pas JNI) via Runtime.Exec. Gardez à l'esprit que vous allez vous attacher au système d'exploitation (ls vs dir). Vous pourrez obtenir une liste de fichiers comme une grande chaîne et sera responsable de la post-traitement dans ce que vous voulez.

J'espère que cela aide.


0 commentaires

5
votes

La seule solution possible pour vous est Java7, puis vous devez utiliser un itérateur.

final Path p = FileSystems.getDefault().getPath("Yourpath");
Files.walk(p).forEach(filePath -> {
        if (Files.isRegularFile(filePath)) {
            //Do something with filePath
        }
});


2 commentaires

Dans Stackoverflow.com/Questtions/3139073/... J'ai posté un exemple simple de comment Obtenez ce fait avec Java 7


chemin.ité () iTère des éléments de noms d'un chemin, pas sur des fichiers dans un répertoire.



0
votes

Si vous pouvez écrire votre code en Java 7 ou en haut, alors suivez est une bonne option.

Files.NewDirectorToryStream (Path Dir)

ici est le docteur Java Doc pour l'API.

J'espère que cela aide.


0 commentaires