Wie ktoś jak można wylistować do listboxa w c#.net wszystkie pliki znajdujące się w wybranym folderze i w folderach znajdujących się w nim? Chodzi mi o pozyskanie takiego efektu mniej więcej w listbox:
“C:\Folder\1.txt
C:\Folder\Subfolder\2.txt”
Od razu zaznaczam, że nie będą wskazane nazwy subfolderów przez użytkownika i program musi z nich wyłapać sam pliki. Nie interesują mnie same ścieżki katalogów tylko plików w głównym folderze i subfolderach.
Konkretnie jej statyczne metody:
DirectoryInfo.GetFiles
i
DirectoryInfo.GetDirectories
Tego typu struktury drzewiaste przechodzi się rekurencyjnie. Tzn. deklarujesz jakąś listę, którą będziesz wypełniał. Zaczynasz z samej góry (“C:”), do listy wrzucasz wszystkie pliki. Później uruchamiasz tę samą funkcję dla wszystkich podkatalogów katalogu w którym jesteś.
Listę, którą wypełniasz deklarujesz jako zmienną na poziomie klasy (wtedy musisz pamiętać o jej wyczyszczeniu przed rozpoczęciem rekursji) lub lepiej przekazujesz (jako referencję) do każdego wywołania.
Mógłbyś się pokusić o wersję wielowątkową np. z użyciem Parallel.Foreach na podkatalogach, ale wtedy musisz użyć np. ConcurrentBag<T>
Pokazanie tego na ekranie np. w listboxie jest rzeczą wtórną i banalną. Nie ma wiele wspólnego z samym pobraniem plików.
Skanowanie całego dysku w ten sposób może chwilę zająć. To mogą być spokojnie dziesiątki milionów plików.
Dzięki! Sporo to pomogło. Jednak mam teraz drobny problem. Gdy listuję sobie pliki za pomocą tego kodu:
foreach (var location in listBox1.Items)
{
string loc = Convert.ToString(location);
listBox3.Items.Add(Directory.GetFiles(loc, "*.*", SearchOption.AllDirectories));
}
To wywala mi błąd, że do niektórych katalogów np. w C:\Recycle Bin\ nie może się dostać co oczywiście mi nie przeszkadzało i chciałem to zignorować przez użycie catch. Tylko jak użyłem catch to już w ogóle nie listowało. Catcha użyłem tak:
foreach (var location in listBox1.Items)
{
string loc = Convert.ToString(location);
try
{
listBox3.Items.Add(Directory.GetFiles(loc, "*.*", SearchOption.AllDirectories));
}
catch
{
}
}
Okej, zastosowałem się do Twoich uwag. Ogólnie metoda Try i Catch w ogóle nie działają teraz pod pętlą each bo ani się nie wypełnia listbox danymi ani catch nie reaguje.
private List<String> DirSearch(string sDir)
{
List<String> files = new List<String>();
try
{
foreach (string f in Directory.GetFiles(sDir))
{
files.Add(f);
}
foreach (string d in Directory.GetDirectories(sDir))
{
files.AddRange(DirSearch(d));
}
}
catch (System.Exception excpt)
{
MessageBox.Show(excpt.Message);
}
return files;
}
Rozwiązanie zwykłe:
public static IEnumerable<string> GetFileList(string fileSearchPattern, string rootFolderPath)
{
Queue<string> pending = new Queue<string>();
pending.Enqueue(rootFolderPath);
string[] tmp;
while (pending.Count > 0)
{
rootFolderPath = pending.Dequeue();
try
{
tmp = Directory.GetFiles(rootFolderPath, fileSearchPattern);
}
catch (UnauthorizedAccessException)
{
continue;
}
for (int i = 0; i < tmp.Length; i++)
{
yield return tmp[i];
}
tmp = Directory.GetDirectories(rootFolderPath);
for (int i = 0; i < tmp.Length; i++)
{
pending.Enqueue(tmp[i]);
}
}
}
Co prawda kod nie wrzuca do listboxa ale z tym już sobie poradzisz chyba. Kody nie są moje pochodzą z internetu ale osobiście polecam drugi. Nie powinien mieć kłopotu z nieautoryzowanym dostępem