2012-09-03 13 views
12

Jestem wymieniając pliki w systemie plików w Javie przy użyciu Apache Commons następujące klasy:mogę sprawdzić rozmiar kolekcji, jak to jest wypełniane

Collection<File> allFiles = FileUtils.listFiles(rootDirectory, null, recursive);

jest to bardzo długi proces i może zająć do 5 minut.

Czy istnieje sposób sprawdzenia rozmiaru kolekcji podczas jej wypełniania?

Próbowałem uzyskać do niego dostęp z oddzielnego wątku, ale po prostu dostałem zero, aż proces był gotowy.

Odpowiedz

2

Można użyć fileutils IOFileFilter.

Collection<File> listFiles = FileUtils.listFiles(new File("."), counter, FileFilterUtils.trueFileFilter()); 

gdzie licznik byłoby wzdłuż linii

IOFileFilter counter = new IOFileFilter() { 

    @Override 
    public boolean accept(File arg0, String arg1) { 
     countCall(); 
     return true; 
    } 

    @Override 
    public boolean accept(File arg0) { 
     countCall(); 
     return true; 
    } 
}; 

i countCall jest metoda, która aktualizuje postęp.

+0

To jest bardzo innowacyjne. Spróbuję i wrócę do ciebie – Redandwhite

11

Dopóki nie otrzymasz wartości zwracanej z metody, nie będziesz mieć dostępu do kolekcji w miarę jej zapełniania, ponieważ nie masz dostępu do zmiennej, której ta metoda używa wewnętrznie.

Można podzielić wyszukiwanie na mniejsze fragmenty, nie używając flagi rekursywnej i samodzielnie obsłużyć rekurencję, aby odebrać kolekcję według katalogu.

Lepszą alternatywą, jeśli używasz Java 7, jest użycie the FileVisitor interface to explore the file system. Ma kilka metod wywoływania zwrotnego, które umożliwiają śledzenie postępu.

+0

+1 za wspomnienie FileViewitor i wywołań zwrotnych – Pyranja

+0

Niestety, muszę używać Java 6, ponieważ aplikacja musi działać na komputerach Mac z wbudowanym JVM (Apple nadal wysyła Java 6!) – Redandwhite

+0

@Redandwhite Myślę, że twoja jedyna opcja jest podzielenie wyszukiwania - chyba, że ​​ktoś inny ma lepszy pomysł. – assylias

1

Domyślam się, że możesz spróbować użyć poleceń specyficznych dla platformy, takich jak przekierowanie wyjścia polecenia listy do pliku tymczasowego i odczytanie go za pomocą interfejsu Java File API.

ls > temp.txt

stworzyłem prosty skrypt, który wyświetla listę plików w danym indeksie.

#!/bin/bash 

RANGE_UP=$2 
RANGE_BOT=$1 

CURRENT_CNTR=0 

FILENAME=._m_ls 

ls -w 1 > $FILENAME 
while read line 
do 
    if [ $CURRENT_CNTR -le $RANGE_UP -a $CURRENT_CNTR -gt $RANGE_BOT ]; then 
    printf $line"\n" 
    fi 
    CURRENT_CNTR=`expr $CURRENT_CNTR + 1` 
done < $FILENAME 

Teraz można zrobić coś takiego ./ls_range.sh 10000 30000 >temp.txt a następnie odczytać z tego pliku przy użyciu BufferedReader w innym wątku.

1

Jedynym sposobem na zrobienie tego (w przeciwieństwie do java7 lub podzielenie pracy, jak wcześniej sugerowano) byłoby napisanie własnego kodu, aby przeszukać system plików podczas aktualizacji wywołania zwrotnego.

Użyłem kodu z commons-io, i zmodyfikowałem go do twoich potrzeb, oczywiście wymaga on testowania, ale zlicza pliki, które zostały znalezione.

Przykład

interface Counter { 
    void foundFile(File file); 
} 

final class FileSearcher { 
    public static Collection<File> listFiles(File root, FileFilter filter, Counter counter) { 
     Collection<File> files = new ArrayList<File>(); 
     File[] found = root.listFiles(filter); 

     if (found != null) { 
      for (int i = 0; i < found.length; i++) { 
       if (found[i].isDirectory()) { 
        files.addAll(listFiles(found[i], filter, counter)); 
       } else { 
        files.add(found[i]); 
        counter.foundFile(found[i]); 
       } 
      } 
     } 

     return files; 
    } 
} 

a następnie używać go tak:

final AtomicInteger inte = new AtomicInteger(0); 
FileSearcher.listFiles(new File("C:/"), null, new Counter() { 
    @Override 
    public void foundFile(File file) { 
     System.out.println("found file number " + inte.addAndGet(1)); 
    } 
}); 
Powiązane problemy