Input/Output 20Mb Textdatei zeilenweise auslesen

toenjes

Mitglied
Moin,

ich möchte eine relativ große Textdatei (bis zu 20MB) zeilenweise durchgehen und dann jede Zeile verarbeiten. Zurzeit mache ich das mit BufferedReader - aber das dauert zu lange.

Gibt es eine schnellere Möglichkeit eine Textdatei zu verarbeiten?

Kann man in einer Textdatei gleich zu einer bestimmten Zeile springen und von dort aus dann weiter Arbeiten?
 
wie lange dauert es denn?
viel zu lange oder sehr viel zu lange oder fast eine Ewigkeit oder könnte schon schneller sein.

gehst du das ganze einmal oder mehrmals durch?

Liegt der Zeitverbrauch tatsächlich am Einlesen? Du könntest hierzu deine ganze Datei einmal in ein String[] oder eine List<String> einlesen, dann einen Timestamp setzen und die Verarbeitung deiner Daten aus der liste starten und beim beenden wieder einen Timestamp setzen. Dann siehst du was wie lange braucht. 20MB sollten eigentlich locker in den Arbeitsspeicher passen.
 
ich arbeite taeglich mit GB an daten... was soll bei 20MB bitte gross sein?!

zeig mal lieber Code - ich befuerchte die Optimierung liegt nicht im Verwenden anderer Klassen....
 
Ich hätte vielleicht dran denken sollen zu erwähnen das ich grade mit JSP ein wenig rumspiele. Wenn die die Klasse über das JRE normal laufen lasse ist die Laufzeit wirklich nicht sehr dramatisch, über den WebServer (Glass Fisch 3) aber schon (und mein Server hat nur 1GB Ram und nicht 4 wie mein PC -.-)

Hier die Methode zum auslesen der Datei:

Java:
public String printFile() {
        String print = "";
        try {
		BufferedReader in = new BufferedReader(new FileReader(file));
		String zeile = null;
		while ((zeile = in.readLine()) != null) 
			print += zeile+"<br>";
	} catch (IOException e) {
		e.printStackTrace();
	}

        return print;
    }
 
das Problem hier ist ein bekanntes und vom Reader unabhängig,
es ist die Addition der Strings per Schleife,
bei jeder neuen Zeile müssen die bisherigen 15 MB String in eine neue Variable kopiert werden usw.,
so schaffst du dir GB an Arbeit,

verwende StringBuilder mit append(), dann geht das rasend schnell
 
Was passiert denn weiter mit dem String, der von [c]printFile()[/c] erzeugt wird? Wenn der anschließend wieder nur z.B. auf der Standardausgabe ausgegeben werden soll, ist es unnötig, vorher die gesamte Datei einlesen zu wollen.

Beispiel, wo zeichenweise gelesen und sofort ausgegeben wird:
Java:
public void printFile() {
    try {
        BufferedReader in = new BufferedReader(new FileReader(file));
        int c;
        while ((c = in.read()) != -1) 
            System.out.print((char)c);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

Beispiel, wo zeilenweise gelesen und sofort ausgegeben wird:
Java:
public void printFile() {
    try {
        BufferedReader in = new BufferedReader(new FileReader(file));
        String line;
        while ((line = in.readLine()) != null) 
            System.out.println(line);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

Welche der beiden Varianten besser geeignet ist, müsste dann im Zweifelsfall nachgemessen werden. (Es gibt noch andere Möglichkeiten, die theoretisch noch schneller sein sollten, aber die sehen vor allem hässlicher aus. 😉)

Wenn der Dateiinhalt doch gespeichert werden soll/muss, ist die von SlaterB vorgeschlagene Variante eine einfache und effiziente.

Ark
 
okay, schonmal danke für die Hinweise, ich hab den Code nun abgeändert:

Java:
public String printFile() {
        StringBuilder print = new StringBuilder();
        try {
                Scanner in = new Scanner(new FileReader(file));
		String zeile = null;
		while (in.hasNextLine()) {
			try {
                            print.append(in.nextLine());
                            print.append("<br>");
                            System.out.println(in.nextLine());
                        } catch (NoSuchElementException e) {
                            e.printStackTrace();
                        }

                }
	} catch (IOException e) {
		e.printStackTrace();
	}

        return print.toString();
    }

Jetzt gehts schonmal deutlich schneller - aber immer noch zu langsam für meinen Geschmack, gibts da noch weitere Optimierungsmöglichkeiten?
 
> print.append(in.nextLine());
> print.append("<br>");
> System.out.println(in.nextLine());
hier wird 50% in print geaddet, 50% ohne hasNextLine()-Prüfung ausgegeben, ist das dein Ziel?
siehe lieber Code von Ark, 2 Min. vor deinem gepostet


was genau heißt eigentlich langsam?
die System.out.println-Ausgabe könnte für sich 100x länger dauern als das restliche Einlesen,

try/catch in der Schleife ständig neu aufgebaut muss vielleicht wirklich sein, ob das Zeit kostet?
alles eigentlich langsam im unmessbaren Bereich, bist du bei 1 sec für 20 MB, oder noch deutlich drüber?
 
so okay, das addieren der Wertr war sowieso nur um zu sehen ob das Script funkioniert, jetzt habe ich nur noch einmal append - und das script läuft rasent schnell 🙂

Das eigentliche schwere bzw. zeitaufwändiger sind die Operationen die nun bei jeden Schleifendurchlauf kommen...

was genau heißt eigentlich langsam?
die System.out.println-Ausgabe könnte für sich 100x länger dauern als das restliche Einlesen,

try/catch in der Schleife ständig neu aufgebaut muss vielleicht wirklich sein, ob das Zeit kostet?
alles eigentlich langsam im unmessbaren Bereich, bist du bei 1 sec für 20 MB, oder noch deutlich drüber?

naja, das script hat vorher immer knapp 10 minuten gedauert, und mein server ist um einiges langsamer als mein PC, jetzt wo ich das entfernt habe gehts wie gesagt 🙂
 

Zurück
Oben