Effizientes einlesen von großen Textdateien

  • Hallo,


    ich lese gerade Textdateien (CSV) ein und verarbeite diese Zeilenweise. Das funktioniert eigentlich soweit so gut. ich habe beispielsweise eine 7 MB große Textdatei mit ~73.000 Zeilen.
    Mit einem ZeilenCounter lasse ich ich mir alle 5000 Zeilen den aktuellen Zeilenstand ausgeben. Für 73k Zeilen hat nun ein durchlauf ca. 5 Minuten gedauert.



    Das ist mir viel zu lang, vorallem wenn ich bedenke dass ich eine weitere Datei haben mit 130 MB und ~120.000 Zeilen



    Kann man das beschleunigen?


    Thnx im voraus und VG
    Mrt

  • dafür müsstest du aber mal deinen code zeigen :)

    Ich möchte gerne in meiner App öffentliche Nahverkehrsdaten (GTFS) öffnen, wie zB. das von Berlin. Die gezippte Datei ist beispielsweise ca. 30 MB groß. Entpackt hat beispielsweise die trips.txt etwas über 11 MB mit knapp 232.000 Zeilen.


    Hier die Methode welche die Datei Zeilenweise ausließt (achja, die Dateien sind entpackt im assets Ordner, was ja perse etwas langsamer sein soll als zB SD Karte):


    EDIT: Habe einiges optimiert, siehe "AUSkommentare" ;)


    UInd hier das zerlegen der einzelnen Zeile:

  • Es ist wichtig erstmal rauszufinden was den leseprozess so langsam macht. Ich glaube nicht dass das einlesen solang dauert, vermutlich wird parseTripsByLine extrem langsam sein. Wie mir scheint verwendest du eine third party bibliothek um deine Strings aufzuteilen. Kannst du mal versuchen die StringUtils.chopFirstAndLast methode wegzulassen und dann nochmal zu messen wieviel zeit das einlesen benötigt? Es ist erstmal egal ob interpretierbare werte durch das weglassen der methode herauskommen. Es geht ja nur um das debugging.

  • Wie mir scheint verwendest du eine third party bibliothek um deine Strings aufzuteilen. Kannst du mal versuchen die StringUtils.chopFirstAndLast methode wegzulassen und dann nochmal zu messen wieviel zeit das einlesen benötigt?

    Es ist eine FirstPartyLibrary ;)

    Java
    public static String chopFirstAndLast(String rawString)
        {
            return rawString.substring(1, rawString.length()-1);
        }

    Nur ne statische Methode, die das erste und letze Gänsefüßchen wegmacht. Aber ich stoppe mal die Zeit. Hm ok krass, dass da ne Minute unterschied ist, hätt ich nicht gedacht.:


    Alle 10.000 Zeilen lasse ich mir nen log auf die console ausgeben:


    - 10.000 Zeilen mit der chop*-Methode ~ 150 Sek (~2,5 Min.) und 730.000 byte DB größe
    - 10.000 Zeilen ohne der chop*-Methode ~ 90 Sek (~1,5 Min.) und dafür 820.000 byte DB größe

  • du sagtest im ersten post das dauert 5min, also doch nicht ganz soviel :P
    2,5min waren aber mMn auch zuviel, ich denke auch 90s ist noch zuviel.
    Mhh mach mal alle textverändernden sachen raus und teste das reine auslesen. Vorallem trenne das Auslesen, vom in die Datenbank schreiben und messe beide Zeiten. Es kann nämlich auch sein das jetzt die 90s nicht durch das auslesen der daten aus dem File zustande kommen sondern durch das schreiben in die Datenbank.


    Erst wenn du die Messdaten vom reinen lesen und vom reinen in die Datenbank schreiben hast, kannst du dann irgendwelche string-operationen auf deine strings anwenden. Nach jeder String-Operation würde ich dann nochmal messen und schauen warum es aufeinmal eine Minute länger dauert.


    JavaScript
    public static String chopFirstAndLast(String rawString)
        {
            return rawString.substring(1, rawString.length()-1);
        }

    Das solltest du vielleicht auch noch mit dem hier ersetzen.


    Java
    public static String chopFirstAndLast(String rawString)
        {
            return rawString.replace('"', '');
        }
  • Du arbeitest 73.000 Einträge zeilenweise ab, gibst 73.000 Logausgaben aus, erstellst 73.000 Arrays über eine String-Methode und erzeugst 73.000 Datenbankeinträge.
    Ist Dir schon einmal der Gedanke gekommen, dass das ganz eventuell ein kleines bisschen Zeit braucht?
    Deutlich weniger als von Hand, aber trotzdem.


    Das LG G3 ist auch etwas betagt und daher etwas langsam.


    Ich mein ja nur. 73.000x nix machen mit der Low-Level-Sprache C auf einem 1.6GHz Quadcore it 8GB RAM braucht ungefähr 0.02 Sekunden.


    Zitat

    Dauer: 0.024070


    (Bei leerer Schleife ohne statische Variable 0.000355...)


    Bau sowas mal in Java nach und teste das mal direkt auf Deinem Ubuntu und dann auf Deinem LG G3.


    Optimierungspunkt 1)
    Nimm irgendwie die Datenbankzugriffe raus. Vermeide Operationen auf dem Dateisystem generell.
    Du könntest beispielsweise Dateneinträge sammeln und alle 100 Durchläufe im Pulk senden. (Zu langes Sammeln frisst Dir den Speicher weg.)


    Optimierubgspunkt 2)
    Importier den Kram mal in Excel, LibreOffice Calc oder eine ähnliche Anwendung. Da wartest Du auch ein bisschen.
    Leb also einfach damit, dass das dauert und pack den Vorgang in den Hintergrund. Du kannst ja nen unbestimmten Fortschrittsbalken anzeigen und am Ende eine Notification senden.

    Je mehr Käse, desto mehr Löcher.
    Je mehr Löcher, desto weniger Käse.
    Daraus folgt: je mehr Käse, desto weniger Käse.


    »Dies ist ein Forum. Schreibt Eure Fragen in das Forum, nicht per PN!«

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!