2009-12-28 14 views
5

Hier ist der Code Ich verwende:C# Directory.GetFiles Gedächtnis-Hilfe

using (StreamWriter output = new StreamWriter(Path.Combine(masterdestination, "Master.txt"))) 
{ 
    string masterfolders = sourcefolder1; 
    string[] filess = Directory.GetFiles(masterfolders, "*.txt"); 
    foreach (string file in filess) 
    { 
     output.WriteLine(Path.GetFileName(file)); 
    } 
} 

Dieser Code für alle Dateien in dem angegebenen Verzeichnis für jede txt-Datei suchen. Diese Verzeichnisse enthalten manchmal 2 Millionen Dateien.

Überwachung dieses Prozesses, während es läuft Ich habe gesehen, dass es bis zu 800 MB Speicherverbrauch klettern. Gibt es eine Möglichkeit, die Geschwindigkeit dieses Prozesses zu erhalten und den Speicher zu begrenzen? Oder es lesen und ablegen und weitermachen? Hash-tabelle? Jede Idee wäre großartig.

+0

800K? Meinst du 800MB? –

+1

Warum ist 1 MB Speicherverbrauch ein Problem?Über eine Million Dateien? –

+0

800 MB ist, was ich –

Antwort

14

Directory.GetFiles wirklich saugt. Wenn Sie .NET 4.0 verwenden können, sollten Sie sich mit Directory.EnumerateFiles beschäftigen. Aus der Dokumentation:

Die EnumerateFiles und GetFiles Methoden unterscheiden sich wie folgt: Wenn Sie Verwendung EnumerateFiles Sie Aufzählen der Sammlung von Namen , bevor die ganze Sammlung ist zurück beginnen; Wenn Sie GetFiles verwenden, müssen Sie warten, bis das gesamte Array der Namen zurückgegeben wird, bevor Sie auf das Array zugreifen können. Wenn Sie also mit vielen Dateien und Verzeichnisse arbeiten, können EnumerateFiles effizienter sein.

+0

Ich hatte keine Ahnung, dass sie das hinzufügten. Nett! – BFree

+0

@BFree- Es ist sicher schöner! Es ist eines der Dinge in .NET 4.0, auf die ich mich freue! – RichardOD

+0

Ich glaube, dass die Mono-Implementierung von .Net auch das hat, also könnten Sie die Mono-Bibliotheken verwenden, um über die Dateien zu iterieren, wenn .Net 4 keine Option ist. –

0

in der Antwort here erwähnt als ob .NET 4.0 verwenden, können Sie die statische EnumerateFiles Methode auf dem Directory-Klasse verwenden, um eine IEnumerable<string> stattdessen bekommen von eine Zeichenfolge [], die zu dem gesamten Speicherverbrauch führt.

Wenn Sie mit einer .NET-Version vor .NET 4.0 arbeiten, können Sie diese Funktionalität leicht nachahmen, indem Sie die Methoden FindFirstFileEx, FindNextFile usw. über die P/Invoke-Ebene aufrufen.

Dann würden Sie für jede Datei, die von einem Aufruf von FindFirstFile/FindNextFile zurückgegeben wird, den Artikel zurückgeben.

Dies verringert den Speicherverbrauch wie EnumerateFiles für Verzeichnisse mit einer großen Anzahl von Dateien, weil Sie sie nicht alle in ein Array im Voraus laden, sondern sie für die Verarbeitung liefern, wie Sie sie finden.

1

Wenn Sie Fx4 nicht verwenden können, sollten Sie Ihren eigenen FileEnumerator schreiben. Hier ist one example.

+0

+1. Ich würde so etwas als Alternative vorschlagen. Ich denke CodeProject hat auch etwas ähnliches. – RichardOD

1

Directory.GetFiles muss eine Liste aller übereinstimmenden Dateien erstellen, bevor es zurückkehren kann. Nur dann können Sie sie aufzählen. Natürlich ist es teuer, wenn es viele passende Dateien gibt. Es kann sogar intern eine Liste aller Dateien erstellen.

Wenn Sie .NET 4.0 verwenden können, dann könnten Sie Directory.EnumerateFiles verwenden, die dieses Problem vermeidet, indem Sie eine Datei nach der anderen wiederherstellen. Wenn Sie nicht können, würde ich vorschlagen, dass Sie dies in C++ statt C# schreiben.

In C++ können Sie FindFirstFile verwenden, die gleichzeitig die Dateien an Sie zurückgibt.

// iterate though the files in this directory 
// 
TCHAR szWild[MAX_PATH]; 
PathCombine(szWild, masterfolders, _T("*.txt")); 

WIN32_FIND_DATA fd; 
HANDLE hFind = FindFirstFile(szWild, &fd); 
if (INVALID_HANDLE_VALUE != hFind) 
{ 
    do { 
    TCHAR szFileName[MAX_PATH]; 
    PathCombine(szFileName, masterfolders, fd.cFileName); 

    // write szFilename to output stream.. 

    } while (FindNextFile(hFind, &fd)); 

    FindClose (hFind); 
} 
+0

Was benutzt das? –

+0

Nicht sicher, was TCHAR und WIN32_FInD-Data verwenden oder Referenzen sind. –

+0

ahh n/m hat es t/y –

Verwandte Themen