Ho implementato (in Java) un Iterator abbastanza semplice per restituire i nomi dei file in una struttura di directory ricorsiva e dopo circa 2300 file non è riuscito "Troppi file aperti nel sistema" (l'errore era in realtà nel tentativo di caricare una classe, ma presumo che l'elenco di directory fosse il colpevole).Errore "Troppi file aperti nel sistema" mentre si elenca una struttura di directory ricorsiva
La struttura dati gestita dall'iteratore è una pila contenente i contenuti delle directory aperte a ciascun livello.
La logica attuale è piuttosto semplice:
private static class DirectoryIterator implements Iterator<String> {
private Stack<File[]> directories;
private FilenameFilter filter;
private Stack<Integer> positions = new Stack<Integer>();
private boolean recurse;
private String next = null;
public DirectoryIterator(Stack<File[]> directories, boolean recurse, FilenameFilter filter) {
this.directories = directories;
this.recurse = recurse;
this.filter = filter;
positions.push(0);
advance();
}
public boolean hasNext() {
return next != null;
}
public String next() {
String s = next;
advance();
return s;
}
public void remove() {
throw new UnsupportedOperationException();
}
private void advance() {
if (directories.isEmpty()) {
next = null;
} else {
File[] files = directories.peek();
while (positions.peek() >= files.length) {
directories.pop();
positions.pop();
if (directories.isEmpty()) {
next = null;
return;
}
files = directories.peek();
}
File nextFile = files[positions.peek()];
if (nextFile.isDirectory()) {
int p = positions.pop() + 1;
positions.push(p);
if (recurse) {
directories.push(nextFile.listFiles(filter));
positions.push(0);
advance();
} else {
advance();
}
} else {
next = nextFile.toURI().toString();
count++;
if (count % 100 == 0) {
System.err.println(count + " " + next);
}
int p = positions.pop() + 1;
positions.push(p);
}
}
}
}
vorrei capire quanti "open files" questo richiede. In quali circostanze questo algoritmo "apre" un file e quando si chiude nuovamente?
Ho visto alcuni di codice pulito utilizzando Java o Java 7 8, ma sono costretti a Java 6.
appena eseguito il codice su un filesystem con oltre 1.000.000 di file, e non capisco il problema che si sta vedendo. Sto usando JDK 1.6.0_34 su Windows. Forse il problema è altrove nel codice? Puoi pubblicare il codice per 'FilenameFilter' che stai utilizzando? Questo potrebbe essere il problema. – msandiford
Potrebbe essere che il tuo filesystem non sia così profondo, quindi le risorse vengono restituite al sistema operativo dal GC. O forse il tuo sistema operativo ha un limite maggiore per i file aperti. –
Sì, sono rimasto sveglio la notte scorsa chiedendomi se il FileNameFilter fosse la colpa. Ma no: il metodo accept() restituisce il nuovo file (dir, name) .isDirectory() || pattern.matcher (name) .matches(); ' –