Löschen einer großen Anzahl (>100 KB) der Dateien, die mit c# unter Beibehaltung der Leistung in einer web-Anwendung?
Ich versuche zu entfernen, großen Anzahl von Dateien von einem Ort (von groß meine ich über 100000), wobei die Aktion ist initated von einer web-Seite. Offensichtlich, ich konnte einfach
string[] files = System.IO.Directory.GetFiles("path with files to delete");
foreach (var file in files) {
IO.File.Delete(file);
}
Verzeichnis.GetFiles
http://msdn.microsoft.com/en-us/library/wz42302f.aspx
Diese Methode wurde bereits gepostet ein paar mal:
So löschen Sie alle Dateien und Ordner in einem Verzeichnis?
und
Löschen von Dateien aus dem Verzeichnis, wenn der Dateiname enthält ein bestimmtes Wort
Aber das problem mit dieser Methode ist, dass, wenn Sie sagen, hundert tausend Dateien wird es ein performance-Problem, wie es zu generieren, die alle filepaths zuerst, bevor die Schleife durch Sie.
Hinzu, wenn eine web-Seite wartet eine Antwort ab, eine Methode, die die Durchführung dieser, wie Sie sich vorstellen können, wird es Aussehen, ein bisschen Müll!
Einen Gedanken, den ich hatte war, um wrap up in ein asychrnonous web-service-Aufruf, und wenn es abgeschlossen es feuert wieder eine Antwort auf die web-Seite zu sagen, dass Sie entfernt wurden? Vielleicht setzen die delete-Methode in einem separaten thread? Oder vielleicht sogar eine separate batch-Prozess ausführen löschen?
Ich habe ein ähnliches Problem, wenn Sie versuchen, um die Anzahl der Dateien in einem Verzeichnis - wenn es enthält eine große Anzahl von Dateien.
Ich Frage mich, ob dies alles ein wenig übertrieben? I. e. gibt es eine einfachere Methode, um damit umzugehen? Jede Hilfe würde geschätzt werden.
- Ich bin mir nicht sicher über C#, aber in der Regel keine so gute Idee, um große Anzahl von Dateien in einem einzigen Verzeichnis.
- Sie haben erwähnt es selbst,
asynchronous
ist das Stichwort. - Zu "Sands" - Vertrauen Sie mir, ich habe nicht diese Entscheidung treffen!! 🙂
- Ich denke, das ist genau, warum es nützlich sein würde, um eine performante Möglichkeit löschen eine große Anzahl von Dateien in einem einzigen Verzeichnis, falls Sie sich in dieser position.
Du musst angemeldet sein, um einen Kommentar abzugeben.
GetFiles
ist extrem langsam.Unten eine Implementierung eines schnellen Win32 Verpackung für
GetFiles
verwenden Sie es in Kombination mit einem neuen Thread und eine AJAX-Funktion wie:GetFilesUnmanaged(@"C:\myDir", "*.txt*).GetEnumerator().MoveNext()
.Nutzung
GetFilesUnmanaged(@"C:\myDir", "*.txt").GetEnumerator().MoveNext()
; es ist ein sehr Billig nennen, im Gegensatz zu Standard -GetFiles
, und wenn es etwas zurückgibt; der Prozess hat noch nicht fertig :-).Können Sie alle Ihre Dateien im selben Verzeichnis?
Wenn dem so ist, warum rufst du nicht einfach
Directory.Delete(string,bool)
auf den Ordner, den Sie löschen möchten?Wenn Sie bereits eine Liste von Datei-Pfade, die Sie wollen, um loszuwerden, könnte man wirklich bessere Ergebnisse erzielen, indem Sie diese in ein temp-dir, dann löschen Sie nicht löschen, jede Datei manuell.
Cheers,
Florian
Tun es in einem separaten thread, oder posten Sie eine Nachricht auf eine queue (vielleicht MSMQ?) wo andere Anwendung (vielleicht ein windows service) abonniert, die Warteschlange und führt die Befehle (z.B. "Löschen e:\dir*.txt"), in einem eigenen Prozess.
Sollte die Nachricht wohl nur den Namen des Ordners. Wenn Sie so etwas wie NServiceBus - und Transaktions-Warteschlangen, dann können Sie posten Sie Ihre Nachricht und senden Sie sofort, solange die Nachricht wurde erfolgreich gebucht. Wenn es ein problem gibt, eigentlich die Verarbeitung der Nachricht, dann werde es wiederholen, und schließlich gehen Sie auf eine error-queue, die Sie sehen können-und Wartungsarbeiten auf.
Dass mehr als 1000 Dateien in ein Verzeichnis ist ein riesiges problem.
Wenn Sie sind in der Entwicklungsphase, nun, Sie sollten in Erwägung ziehen, in eine algo die Dateien in einer zufälligen Ordner (in Ihrem root-Ordner) mit einer Gewissheit von der Anzahl der Dateien in diesem Ordner werden unter 1024.
Etwas wie
Während dies zu tun, stellen Sie sicher, dass jedes mal, wenn Sie eine Datei erstellen, fügen Sie es in eine HashMap oder Liste gleichzeitig (der Pfad). In regelmäßigen Abständen serialisieren, dies mit so etwas wie JSON.net auf das Dateisystem(Integrität Willen, so dass selbst wenn der Dienst ausfällt, können Sie wieder die Datei-Liste aus der serialisierten form).
Wenn Sie möchten, zu bereinigen, die Dateien oder Abfrage unter Ihnen, zuerst eine lookup-dieser HashMap oder Liste und dann
handeln auf die Datei. Das ist besser als
System.IO.Directory.GetFiles
Boot-die Arbeit in einem worker-thread, und dann wieder Ihre Antwort an den Benutzer.
Ich würde Flagge bis eine application-variable, um zu sagen, dass Sie tun, "das große löschen "job" zu stoppen, in dem mehrere threads die gleiche Arbeit. Sie können dann die Umfrage einer anderen Seite, die geben könnte Sie ein Fortschritt update von der Anzahl der Dateien, die entfernt so viel zu, wenn Sie wollten?
Nur eine Abfrage, aber warum so viele Dateien?
Könnte man erstellen Sie eine einfache ajax-webmethod in Ihre aspx-code hinter, und rufen Sie es mit javascript.
Die beste Wahl (imho) wäre ein separater Prozess zum löschen/Anzahl der Dateien und überprüfen Sie die Fortschritte durch polling sonst bekommen Sie vielleicht Probleme mit der browser-timeouts.
Wow. Ich denke, Sie sind definitiv auf dem richtigen Weg mit einigen anderen Dienst oder Person kümmert sich um die zu löschen. Dabei könnte man auch Methoden bereitstellen, die für die Verfolgung der Prozess der löschen und zeigt das Ergebnis an den Benutzer asynchron javascript.
Wie schon andere gesagt haben, dies auszudrücken, in einem anderen Prozess ist eine tolle Idee. Sie wollen nicht IIS-Beschlag-Mittel verwenden, so lange laufende jobs. Ein weiterer Grund dafür ist die Sicherheit. Sie vielleicht nicht wollen, zu geben, Ihre Arbeit Prozess, die Fähigkeit zum löschen von Dateien von der Festplatte.
Ich weiß, es ist altes Thema, aber neben Jan Jongboom Antwort, die ich vorschlagen ähnliche Lösung, die ist ziemlich performant und mehr universal. Meine Lösung wurde gebaut, um schnell zu entfernen Verzeichnis in der DFS-Struktur mit Unterstützung für lange Dateinamen (>255 chars).
Der erste Unterschied ist in der DLL-import-Deklaration.
WIN32_FIND_DATA-Struktur ist auch etwas anders:
Um lange Pfade, der Pfad muss wie folgt vorbereitet:
und hier ist der main-Methode:
konnten wir natürlich weiter gehen und speichern, Verzeichnisse in separaten Liste außerhalb der Methode und löschen Sie Sie später in eine andere Methode, die könnte wie folgt Aussehen:
Einige Verbesserungen in der Geschwindigkeit, in der back-end:
Verwenden
Directory.EnumerateFiles(..)
: diese wird Durchlaufen-Dateienohne zu warten, nachdem alle Dateien abgerufen wurden.
Verwenden
Parallel.Foreach(..)
: dies löscht Dateien gleichzeitig.Sollte es schneller sein, aber anscheinend sind die HTTP-Anforderung würde noch sein timeout mit der großen Anzahl von Dateien, also das back-end-Prozess ausgeführt werden sollen, in separaten worker-thread und teilt das Ergebnis zurück an den web-client nach Verarbeitung.