it-swarm.com.de

Wie kann man schnell eine große Datei nach einem String in Java durchsuchen?

Ich versuche, eine große Textdatei (400 MB) nach einer bestimmten Zeichenfolge zu durchsuchen, indem ich Folgendes verwende:

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 und andere große Dateien dauert es viel zu lange (> 10 Minuten).

Was wäre der schnellste und effizienteste Weg, dies zu tun?

Ich habe jetzt folgendes geändert und es ist innerhalb von Sekunden abgeschlossen -

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);
    }
8
Chief DMG

1. Finden Sie heraus, wie lange Sie brauchen, um den gesamten Inhalt der Datei zu lesen, und wie lange Sie brauchen, um sie nach Ihrem Muster zu durchsuchen.

wenn Ihre Ergebnisse von der Lesezeit dominiert werden (und davon ausgegangen wird, dass Sie sie richtig gelesen haben, also Kanäle oder zumindest gepufferte Leser), gibt es nicht viel zu tun.

wenn die Scan-Zeit dominiert, können Sie alle Zeilen lesen und dann kleine Stapel von Zeilen zur Suche in eine Arbeitswarteschlange senden, in der mehrere Threads Zeilenstapel aufnehmen und darin suchen können.

Spielfiguren

  • unter der Annahme von 50 MB/s als Lesegeschwindigkeit der Festplatte (und das ist nach modernen Maßstäben langsam) sollten Sie in der Lage sein, die gesamte Datei in weniger als 10 Sekunden in den Speicher einzulesen.
  • ein Blick auf die MD5-Benchmarks für die Hashing-Geschwindigkeit (Beispiel hier ) zeigt, dass die Hashing-Geschwindigkeit mindestens so schnell (oft schneller) sein kann als die Lesegeschwindigkeit der Festplatte. Außerdem ist die Suche nach Zeichenfolgen schneller, einfacher und parallelisiert besser als das Hashing.

angesichts dieser beiden Schätzungen kann eine ordnungsgemäße Implementierung Ihrer Meinung nach leicht zu einer Laufzeit in der Größenordnung von 10 Sekunden führen (wenn Sie Suchaufträge starten, während Sie Zeilenstapel lesen) und weitgehend von Ihrer Festplattenlesezeit bestimmt werden.

6
radai

Scanner ist in diesem Fall einfach nicht sinnvoll. Unter der Haube werden alle Arten von Eingaben analysiert, überprüft, zwischengespeichert und so weiter. Wenn Ihr Fall einfach "über alle Zeilen einer Datei iterieren" ist, verwenden Sie etwas, das auf einem einfachen BufferedReader basiert.

In Ihrem speziellen Fall empfehle ich die Verwendung von Files.lines.

Beispiel:

  long count = Files.lines(Paths.get("testfile.txt"))
     .filter(s -> s.contains("particularString"))
     .count();
  System.out.println(count);

(Beachten Sie, dass dieser spezielle Fall der Streaming-API wahrscheinlich nicht das abdeckt, was Sie tatsächlich erreichen möchten. Leider gibt Ihre Frage nicht an, was das Ergebnis der Methode sein soll.)

Auf meinem System bekomme ich ungefähr 15% der Scanner-Laufzeit mit Files.lines () oder einem gepufferten Reader.

0
mtj