2010-10-21 17 views
6

Ich habe eine Textdatei mit 21000 Zeichenfolgen (jeweils eine Zeile) und 500 MB anderen Textdateien (Maily Quellcodes). Für jede Zeichenfolge muss ich feststellen, ob sie in einer dieser Dateien enthalten ist. Ich habe ein Programm geschrieben, das den Job erledigt, aber seine Leistung ist schrecklich (es würde das in ein paar Tagen tun, ich muss den Job in maximal 5-6 Stunden erledigt haben).
Ich bin mit C#, Visual Studio 2010Suche nach mehreren Zeichenfolgen in mehreren Dateien

Ich habe einige Fragen in Bezug auf mein Problem zu schreiben:
a) Welcher Ansatz ist besser?

foreach(string s in StringsToSearch) 
{ 
    //scan all files and break when string is found 
} 

oder

foreach(string f in Files) 
{ 
    //search that file for each string that is not already found 
} 

b) Ist es besser, eine Datei Zeile für Zeile

StreamReader r = new StreamReader(file); 
while(!r.EndOfStream) 
{ 
    string s = r.ReadLine(); 
    //... if(s.Contains(xxx)); 
} 

oder

StreamReader r = new StreamReader(file); 
string s = r.ReadToEnd(); 
//if(s.Contains(xxx)); 

c) Einfädeln Leistung verbessern würde zu scannen und wie das zu tun?
d) Gibt es eine Software, die das tun kann, damit ich meinen eigenen Code nicht schreiben muss?

+0

tun müssen, um das Programm zu schreiben? Windows hat fainstr eingebaut. Sie können eine for-Schleife verwenden, die diese anderen Dateien parallel durchsuchen könnte. –

+0

Definitiv keine korrekte/vollständige Antwort, aber nicht alle (500MB!) Dateien für jeden String laden. Sobald Sie die Datei im Speicher haben, führen Sie alle Ihre Aktionen aus. – Bertvan

+0

Ich möchte ganze Datei nacheinander laden, nicht 500 MB Dateien gleichzeitig. – Ichibann

Antwort

3

Sie möchten Datei-I/O minimieren, also ist Ihre erste Idee sehr schlecht, weil Sie die "anderen" Dateien bis zu 21.000 Mal öffnen würden. Sie möchten etwas basierend auf dem zweiten (a1) verwenden. Und wenn diese anderen Dateien nicht übermäßig groß sind, laden Sie sie einmal mit readAllText in den Speicher.

Die Brute-Force-Teil kann verbessert werden, aber ich denke, Sie finden es akzeptabel.

+0

Ist if (text.IndexOf (key)> = 0) schneller als if (text.Contains (key))? – Ichibann

+0

@Ichi: Nein, ich würde erwarten, dass sie genauso schnell sind. –

2
  1. Sowohl a) und b), zweite Option ist effizient
  2. Threading Coz jeden Thread die Leistung nicht verbessern kann würde die Datei von Ihrer Festplatte lesen, so dass die Festplatte zu einem Engpass wird.
  3. sry ich habe keine Ahnung von s/w
  4. für Ihre Zwecke

Thread Schnipsel

 foreach (FileInfo file in FileList) 
     { 
     Thread t = new Thread(new ParameterizedThreadStart(ProcessFileData)); 
     t.Start(file.FullName); 
     }//where processFileData is the method that process the files 

General I/O-Richtlinien

Was sind einige grundlegende Empfehlungen folgt zur Reduzierung E/A-Aktivität Ihres Programms und damit seine Leistung zu verbessern. Wie bei allen Empfehlungen ist es wichtig, die Leistung des zu optimierenden Codes vor und nach der Optimierung zu messen, um sicherzustellen, dass er tatsächlich schneller wird.

  1. Minimieren Sie die Anzahl der Datei Operationen Sie
  2. Gruppe mehrere kleine E/A-Übertragungen in eine große Übertragung durchzuführen.Eine einzelne Schreiben von acht Seiten ist schneller als acht separate Single-Seite schreibt, vor allem, weil es die Festplatte ermöglicht, die Daten in einem Durchgang über die Plattenoberfläche zu schreiben. Weitere Informationen ,
  3. Führen Sie sequentielle Lesevorgänge statt Suche und Lesen kleiner Blöcke von Daten. Der Kernel transparent Cluster E/A-Operationen, die sequenziellen liest viel schneller macht.
  4. Vermeiden Sie, in einer leeren Datei zu springen, bevor Sie Daten schreiben. Das System muss Nullen in den Zwischenraum schreiben, um die Lücke zu füllen. Weitere Informationen finden Sie unter Lesen ist in der Regel billiger als Schreiben Daten.
  5. Verschieben Sie alle E/A-Operationen, bis die zeigen, dass Ihre Anwendung tatsächlich die Daten benötigt.
  6. um Präferenzen System capture nur Benutzerpräferenzen (wie als Fensterpositionen und Ansicht Einstellungen) und nicht die Daten, die kostengünstig neu berechnet werden können.
  7. Gehen Sie nicht davon aus, dass die Zwischenspeicherung von Dateidaten im Speicher Ihre Anwendung beschleunigt. Das Speichern von Dateidaten in Speicher verbessert die Geschwindigkeit, bis Speicher auf die Platte ausgelagert wird, unter , die Sie zahlen den Preis für Zugriff auf die Festplatte noch einmal. Strive eine geeignete Balance zwischen dem Lesen von der Festplatte in den Speicher und Caching
6

zu finden, wenn Sie nur wissen wollen, sind, wenn die Zeichenfolge gefunden wird oder nicht gefunden wird, und brauchen keine weitere Verarbeitung zu tun, dann würde ich vorschlagen, dass du einfach grep benutzt. Grep ist extrem schnell und für genau diese Art von Problem konzipiert.

grep -f strings-file other-files... 

sollte den Trick tun. Ich bin mir sicher, dass es irgendwo draußen eine Windows-Implementierung gibt. Im schlimmsten Fall wird Cygwin es haben.

EDIT: Diese Antworten Frage d)

+0

Ja, trotz des Tags [C#] könnte dies der beste Ansatz sein. –

+0

Ich bin nicht vertraut mit Grep und wie es funktioniert, vielleicht wenig Hilfe, wie man das benutzt? – Ichibann

+0

Grep ist ein sehr verbreitetes Werkzeug in * nix Systemen. Es gibt eine Menge Dokumentation da draußen, also wird es bestimmt ein gutes Tutorial geben. Der vorgeschlagene Befehl sucht nach allen Zeichenfolgen, die in "strings-file" in einer der "anderen Dateien" gefunden wurden, und druckt alle übereinstimmenden Zeilen in "anderen Dateien" aus. Es gibt viele Möglichkeiten, die Ausgabe auf das zu ändern, was Sie benötigen. –

2

Ist die Suche in Echtzeit auf aktuelle 500 MB Text sein? Der Grund, warum ich frage, ist, weil Sie einen Suchindex für die Textdateien erstellen und die Suche durchführen könnten. Es wäre viel schneller ... Werfen Sie einen Blick auf Lucene

Lucene.Net

C# and Lucene to index and search

+0

Es muss nicht in Echtzeit gesucht werden. Es ist eine einmalige Aufgabe. Mach und vergiss es: P – Ichibann

+0

Dann benutze Lucene (ich habe das Windows Search SDK nicht benutzt), um einen kompletten Suchindex zu erstellen und suche danach ... Ich habe Lucene vorher benutzt ... Es ist schnell! – zam6ak