web-dev-qa-db-de.com

Java Der schnellste Weg zum Lesen einer Textdatei mit 2 Millionen Zeilen

Derzeit verwende ich Scanner/Dateileiter und verwende whilenextline. Ich denke, dass diese Methode nicht sehr effizient ist. Gibt es eine andere Methode, um Dateien mit ähnlichen Funktionen zu lesen? 

public void Read(String file) {
        Scanner sc = null;


        try {
            sc = new Scanner(new FileReader(file));

            while (sc.hasNextLine()) {
                String text = sc.nextLine();
                String[] file_Array = text.split(" ", 3);

                if (file_Array[0].equalsIgnoreCase("case")) {
                    //do something
                } else if (file_Array[0].equalsIgnoreCase("object")) {
                    //do something
                } else if (file_Array[0].equalsIgnoreCase("classes")) {
                    //do something
                } else if (file_Array[0].equalsIgnoreCase("function")) {
                    //do something
                } 
                else if (file_Array[0].equalsIgnoreCase("ignore")) {
                    //do something
                }
                else if (file_Array[0].equalsIgnoreCase("display")) {
                    //do something
                }
            }

        } catch (FileNotFoundException e) {
            System.out.println("Input file " + file + " not found");
            System.exit(1);
        } finally {
            sc.close();
        }
    }
26

Sie werden feststellen, dass BufferedReader.readLine() so schnell ist, wie Sie es brauchen: Sie können Millionen von Zeilen pro Sekunde lesen. Es ist wahrscheinlicher, dass die Aufteilung und Verarbeitung von Strings die Performance-Probleme verursacht, auf die Sie stoßen.

29
user207421

Scanner kann nicht so schnell wie BufferedReader sein, da zum Lesen von Textdateien reguläre Ausdrücke verwendet werden, was sie im Vergleich zu BufferedReader langsamer macht. Mit BufferedReader können Sie einen Block aus einer Textdatei lesen.

BufferedReader bf = new BufferedReader(new FileReader("FileName"));

als nächstes können Sie readLine () verwenden, um von bf zu lesen.

Hoffe, es dient deinem Zweck.

5
shamsAAzad

sie können FileChannel und ByteBuffer von Java NIO verwenden. Die ByteBuffer-Größe ist der kritischste Teil beim Lesen von Daten, was ich beobachtet habe. Der folgende Code liest den Inhalt der Datei.

static public void main( String args[] ) throws Exception 
    {
        FileInputStream fileInputStream = new FileInputStream(
                                        new File("sample4.txt"));
        FileChannel fileChannel = fileInputStream.getChannel();
        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);

        fileChannel.read(byteBuffer);
        byteBuffer.flip();
        int limit = byteBuffer.limit();
        while(limit>0)
        {
            System.out.print((char)byteBuffer.get());
            limit--;
        }

        fileChannel.close();
    }

Sie können hier nach '\ n' nach neuer Zeile suchen. Vielen Dank.


Sogar Sie können mit dem Scatter- und Getter-Verfahren Dateien schneller lesen, d. H.

fileChannel.get(buffers);

woher 

      ByteBuffer b1 = ByteBuffer.allocate(B1);
      ByteBuffer b2 = ByteBuffer.allocate(B2);
      ByteBuffer b3 = ByteBuffer.allocate(B3);

      ByteBuffer[] buffers = {b1, b2, b3};

Dies erspart dem Benutzerprozess, mehrere Systemaufrufe durchzuführen (was sehr teuer sein kann), und ermöglicht dem Kernel, die Handhabung der Daten zu optimieren, da er Informationen über die Gesamtübertragung enthält. Wenn mehrere CPUs verfügbar sind, können sogar mehrere Puffer gefüllt und entleert werden gleichzeitig.

Von dieses Buch.

2
Trying

Ich habe einen Gist Vergleich verschiedener Methoden gemacht:

import Java.io.*;
import Java.nio.file.Files;
import Java.nio.file.Paths;
import Java.util.ArrayList;
import Java.util.LinkedList;
import Java.util.List;
import Java.util.Scanner;
import Java.util.function.Function;

public class Main {

    public static void main(String[] args) {

        String path = "resources/testfile.txt";
        measureTime("BufferedReader.readLine() into ArrayList", Main::bufferReaderToLinkedList, path);
        measureTime("BufferedReader.readLine() into LinkedList", Main::bufferReaderToArrayList, path);
        measureTime("Files.readAllLines()", Main::readAllLines, path);
        measureTime("Scanner.nextLine() into ArrayList", Main::scannerArrayList, path);
        measureTime("Scanner.nextLine() into LinkedList", Main::scannerLinkedList, path);
        measureTime("RandomAccessFile.readLine() into ArrayList", Main::randomAccessFileArrayList, path);
        measureTime("RandomAccessFile.readLine() into LinkedList", Main::randomAccessFileLinkedList, path);
        System.out.println("-----------------------------------------------------------");
    }

    private static void measureTime(String name, Function<String, List<String>> fn, String path) {
        System.out.println("-----------------------------------------------------------");
        System.out.println("run: " + name);
        long startTime = System.nanoTime();
        List<String> l = fn.apply(path);
        long estimatedTime = System.nanoTime() - startTime;
        System.out.println("lines: " + l.size());
        System.out.println("estimatedTime: " + estimatedTime / 1_000_000_000.);
    }

    private static List<String> bufferReaderToLinkedList(String path) {
        return bufferReaderToList(path, new LinkedList<>());
    }

    private static List<String> bufferReaderToArrayList(String path) {
        return bufferReaderToList(path, new ArrayList<>());
    }

    private static List<String> bufferReaderToList(String path, List<String> list) {
        BufferedReader reader;
        try {
            reader = new BufferedReader(new FileReader(
                    path));
            String line = reader.readLine();
            while (line != null) {
                line = reader.readLine();
                list.add(line);
            }
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return list;
    }

    private static List<String> readAllLines(String path) {
        try {
            return Files.readAllLines(Paths.get(path));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    private static List<String> randomAccessFileLinkedList(String path) {
        return randomAccessFile(path, new LinkedList<>());
    }

    private static List<String> randomAccessFileArrayList(String path) {
        return randomAccessFile(path, new ArrayList<>());
    }

    private static List<String> randomAccessFile(String path, List<String> list) {
        try {
            RandomAccessFile file = new RandomAccessFile(path, "r");
            String str;
            while ((str = file.readLine()) != null) {
                list.add(str);
            }
            file.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return list;
    }

    private static List<String> scannerLinkedList(String path) {
        return scanner(path, new LinkedList<>());
    }

    private static List<String> scannerArrayList(String path) {
        return scanner(path, new ArrayList<>());
    }

    private static List<String> scanner(String path, List<String> list) {
        try {
            Scanner scanner = new Scanner(new File(path));
            while (scanner.hasNextLine()) {
                list.add(scanner.nextLine());
            }
            scanner.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        return list;
    }


}

führen Sie: BufferedReader.readLine () in ArrayList aus Zeilen: 1000000, geschätzteZeit: 0,105118655

führen Sie: BufferedReader.readLine () in LinkedList aus Zeilen: 1000000, geschätzteZeit: 0,072696934

run: Files.readAllLines (), Zeilen: 1000000, geschätzte Zeit: 0,087753316

führen Sie: Scanner.nextLine () in ArrayList aus Zeilen: 1000000, geschätzte Zeit: 0,743121734

führen Sie: Scanner.nextLine () in LinkedList aus Zeilen: 1000000, geschätzteZeit: 0,867049885

run: RandomAccessFile.readLine () in ArrayList Zeilen: 1000000, geschätzteZeit: 11.413323046

run: RandomAccessFile.readLine () in LinkedList Zeilen: 1000000, geschätzteZeit: 11.423862897

BufferedReader ist die schnellste, Files.readAllLines() ist auch akzeptabel, Scanner ist aufgrund von regex langsam, RandomAccessFile ist inakzeptabel

1
YAMM

Verwenden Sie BufferedReader für den Dateizugriff mit hoher Leistung. Die Standardpuffergröße von 8192 Bytes ist jedoch oft zu klein. Bei großen Dateien können Sie die Puffergröße erhöhen um Größenordnungen erhöhen, um die Leseleistung von Dateien zu verbessern. Zum Beispiel:

BufferedReader br = new BufferedReader("file.dat", 1000 * 8192);
while ((thisLine = br.readLine()) != null) {
    System.out.println(thisLine);
}  
0
mac7

wir aktualisieren gerade diesen Thread. Jetzt haben wir Java 8, um diesen Job zu erledigen:

List<String> lines = Files.readAllLines(Paths.get(file_path);
0
Digao

Sie müssen untersuchen, welcher Teil des Programms Zeit braucht.

Als Antwort von EJP sollten Sie BufferedReader verwenden.

Wenn die Zeichenfolgenverarbeitung wirklich Zeit in Anspruch nimmt, sollten Sie die Verwendung von Threads in Betracht ziehen. Ein Thread liest die Zeilen aus Datei und Warteschlangen. Andere String-Prozessor-Threads werden Zeilen aus der Warteschlange entfernen und sie verarbeiten. Sie müssen untersuchen, wie viele Threads verwendet werden sollen. Die Anzahl der Threads, die Sie in der Anwendung verwenden sollten, muss mit der Anzahl der Kerne in der CPU in Beziehung gesetzt werden. In diesem Fall wird die volle CPU verwendet.

0
nullptr