Wie das schnelle durchsuchen einer großen Datei nach einem String in Java?
Ich bin versucht, suchen eine große text-Datei (400MB) für eine bestimmte Zeichenfolge mit dem folgenden:
File file = new File("fileName.txt");
try {
int count = 0;
Scanner scanner = new Scanner(file);
while(scanner.hasNextLine()) {
if(scanner.nextLine().contains("particularString")) {
count++;
System.out.println("Number of instances of String: " + count);
}
}
} catch (FileNotFoundException e){
System.out.println(e);
}
Dies funktioniert gut für kleine Dateien, aber für diese bestimmte Datei und anderen großen dauert es viel zu lange (>10 min).
Was wäre die Schnellste, effizienteste Weg, dies zu tun?
Habe ich jetzt wie folgt geändert und vervollständigt es innerhalb von Sekunden -
try {
int count = 0;
FileReader fileIn = new FileReader(file);
BufferedReader reader = new BufferedReader(fileIn);
String line;
while((line = reader.readLine()) != null) {
if((line.contains("particularString"))) {
count++;
System.out.println("Number of instances of String " + count);
}
}
}catch (IOException e){
System.out.println(e);
}
- Vergleichen Sie die Geschwindigkeit zu
grep -c particularString fileName.txt
. - Ist es nicht gehen, schneller zu sein, wenn er zuerst liest die gesamte Datei in den Speicher?
- Eine sehr triviale Sache, die nichts mit Ihrer Datei den Zugriff auf die Methodik ist die
System.out.println
Aufruf: wenn Sie eine große Anzahl von spielen, es wird tatsächlich verlangsamen Ihre Ausführung, wie Sie erstellen und drucken einer neuenString
jeder Zeit. Natürlich, dies ist nicht die eigentliche Optimierung, die Sie suchen, hier. - Möglich, Duplikat der what die Schnellste Möglichkeit zu Scannen, eine sehr große Datei, die in java?
- Was ist die Zeit ohne Druck? Wenn immer noch schlechte Leistung, die Sie könnten versuchen
BufferedReader().lines().forEach(..)
zu parallelisieren, das zu Lesen. vielleicht. - Parallelisieren Sie das Lesen? Würden Sie nicht eingeschränkt werden durch disk-IO?
- Hat die Datei eigentlich Linien?
- Die meisten offensichtlich zu beschleunigen, verwenden Sie KEINE Scanner, der sehr langsam im Vergleich zu BufferedReader. Scanner nicht VIEL analysieren.
Du musst angemeldet sein, um einen Kommentar abzugeben.
1. herausfinden, wie lange es dauert, Sie tatsächlich Lesen Sie die gesamte Datei-Inhalt vs wie lange es dauert, um Sie zu Scannen für Ihre Muster.
wenn Sie Ihre Ergebnisse sind geprägt durch die lese-Zeit ist (und assumming Sie Lesen es richtig, so dass die Kanäle oder zumindest gepuffert Leser) gibt es nicht viel zu tun.
wenn Ihr die scan-Zeit dominiert, konnten Sie alle Zeilen gelesen und dann Schiff kleine Mengen von Zeilen gesucht werden, in einer Warteschlange, wo man hätte mehrere threads zum picking-up-Linie von Chargen und die Suche in Ihnen.
Schätzungen
diese 2 Schätzungen, die ich denke, eine ordnungsgemäße Umsetzung können leicht land in dem Sie eine Laufzeit in der Größenordnung von 10 Sekunden (wenn man Auftakt nach Stellenangeboten suchen, wie Sie Lesen Zeile Chargen), und werden überwiegend von Ihrer Festplatte Lesen Zeit.
Scanner ist einfach nicht sinnvoll in diesem Fall. Unter der Haube, es macht alle Arten von input-parsing, - Prüfung, - caching und so weiter. Wenn Ihr Fall ist nur "iterieren über alle Zeilen einer Datei", etwas, das basiert auf einem einfachen BufferedReader.
In Ihrem Fall empfehle ich die Verwendung von Dateien.Linien.
Beispiel:
(Beachten Sie, dass dies insbesondere bei der streaming-api ist wohl nicht das abdeckt, was Sie eigentlich zu erreichen versucht - leider Ihre Frage nicht deuten, was das Ergebnis der Methode sein sollte.)
Auf meinem system, ich bekomme etwa 15% der Scanner-runtime-Dateien.lines() oder einen buffered reader.
Verwendung einer Methode vom Scanner-Objekt - FindWithinHorizon. Scanner wird intern eine FileChannel, die Datei zu Lesen. Und "pattern-matching" wird es am Ende mit einer Boyer-Moore-Algorithmus für effiziente string-Suche.