Announcement

Collapse
No announcement yet.

Große Textdatei in Listbox einlesen

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Große Textdatei in Listbox einlesen

    Hallo,

    ich möchte eine ziemlich grosse Textdatei (> 400.000 Zeilen) in einer Listbox darstellen. Die Datei ist (leider) nicht sortiert - da im Programm aber die Möglichkeit bestehen soll nach bestimmten Kriterien zu suchen bzw. zu filtern muss die Datei wohl komplett geladen sein (oder geht das auch anders?).
    Auch kann (darf) ich die Datei nicht vorher sortieren, da sie, so wie sie uns geliefert wurde angezeigt werden soll.

    So, nun habe ich schon diverse Dinge probiert um diese Datei in einer akzeptablen Zeit in der Listbox darzustellen:
    - ich lese die Daten mittels Streamreader in eine Stringliste:
    List<string> zeile = new List<string>(); --> das geht irre schnell (< 1 sek.)
    - Nun übergebe ich die Daten der Stringlist in einer Schleife mit dem folgenden Befehl an die Listbox:
    listBox1.Items.Add(zeile[i]); --> das dauert (> 5 min.)
    - nächster Versuch: Die StringList an ein Array übergeben und dieses Array an die Listbox übergeben:
    string[] z = zeile.ToArray();
    listBox1.Items.AddRange(z); --> auch das dauert (> 5 min.)
    Weitere Versuche waren noch einen eigenen Thread aus dem Einlese-Prozeß zu machen, was aber auch nicht zu einer schnelleren Verarbeitung geführt hat.
    Ich habe auch schon überlegt, die Textdatei in eine Datenbank zu speichern und sie von dort aus mittels SQL auszulesen. Das ist nicht gewünscht, da dann auf den Zielsystemen auch der SQL-Server installiert sein müsste.

    Kann mir jemand einen Tipp geben, wie ich diese Textdatei in einer akzeptablen Zeit in einer ListBox anzeigen kann ?

    Achso, ja, ich arbeite mit der Entwicklungsumgebung Visual Studio C# 2010 Express.

    Vielen Dank für eure Hilfe.

    Gruß, Karlo

  • #2
    ListView + Virtual Modus (weiß jetzt nicht wie er unter .NET genau heißt). Anzeige sollte in Bruchteil einer Sekunde möglich sein.

    Comment


    • #3
      Schleife durch

      Code:
      listBox1.Items.AddRange(zeile)
      ersetzen.

      Dann wird das Hinzufügen auch automatisch in einen BeginUpdate/EndUpdate Block gepackt damit während dem Hinzufügen nicht ständig die Listbox aktualisiert wird. Jetzt kannst du ja wahrscheinlich während deiner Schleife zugucken wie die vertikale Scrollbar stetig schrumpft (völlig überflüssiger extremer Zeitfresser).

      Wenn das noch reicht siehe Bernhard antwort.

      PS. 400000 Einträge in einer Liste? Magst du deine User nicht das du solche Folterinstrumente implementierst?

      Comment


      • #4
        Erstmal vielen Dank für eure Antworten.

        zu Ralf:

        Schleife durch
        listBox1.Items.AddRange(zeile)
        ersetzen.
        Den Befehl hatte ich schon benutzt. Das bringt leider nichts.

        PS. 400000 Einträge in einer Liste? Magst du deine User nicht das du solche Folterinstrumente implementierst?
        Ich mag meine User sehr gern - deshalb versuche ich denen ja diese Textdatei etwas "komfortabler" darzustellen. Zurzeit wird diese Datei im Texteditor betrachtet und ausgewertet. Wir erhalten diese Datei von einem Forschungsinstitut - Müsste mal nachfragen, ob die uns nicht mögen


        zu Bernhard:

        ListView + Virtual Modus (weiß jetzt nicht wie er unter .NET genau heißt). Anzeige sollte in Bruchteil einer Sekunde möglich sein.
        Das habe ich noch nicht ganz verstanden. Da schau ich mir erstmal die Beispiele in der MSDN an. Vielleicht darf ich diesbezgl. noch mal weitere Fragen stellen. Wenn die Anzeige da wirklich in einem Bruchteil einer Sekunde möglich ist, ist das genau das was ich suche.

        Gruß,

        Karlo

        Comment


        • #5
          Den Befehl hatte ich schon benutzt. Das bringt leider nichts.
          Bezweifle ich. Gerade mal gecheckt mit folgendem Beispiel.

          [Highlight=C#]//Testdaten generieren
          string[] list = new string[400000];
          for (int i = 0; i < 400000; i++)
          list[i] = Membership.GeneratePassword(25, 0);

          // Add
          Stopwatch watch = Stopwatch.StartNew();
          foreach (var text in list)
          listBox1.Items.Add(text);
          textBox1.Text = watch.ElapsedMilliseconds.ToString();

          listBox1.Items.Clear();

          // AddRange
          watch = Stopwatch.StartNew();
          listBox1.Items.AddRange(list);
          textBox2.Text = watch.ElapsedMilliseconds.ToString();[/Highlight]

          Add dauert ca. 70 Sekunden. AddRange ca. 20 Sekunden. Ist zwar auch nicht toll aber trotzdem deutlich schneller.

          Comment


          • #6
            Hallo Ralf,

            zurzeit sieht das Programm folgendermaßen aus:

            Code:
                        .
                        .
                        .
                        if (DateiOeffnen.ShowDialog() == DialogResult.OK)
                        {
                            try
                            {
                                if (File.Exists(DateiOeffnen.FileName))
                                {
                                    // StringList deklarieren
                                    List<string> zeile = new List<string>();
                                    
                                    // Datei mit Streamreader in die StringList schreiben
                                    StreamReader sr = new StreamReader(DateiOeffnen.FileName);
                                    while (!sr.EndOfStream) zeile.Add(sr.ReadLine());
                                    sr.Close();
                                    
                                    string[] FileArray = new string[zeile.Count];
                                    FileArray = zeile.ToArray();
            
                                    listBox1.Items.Clear();
            
                                    Stopwatch watch = Stopwatch.StartNew();
                                    watch = Stopwatch.StartNew(); 
                                    listBox1.Items.AddRange(FileArray); 
                                    textBox1.Text = watch.ElapsedMilliseconds.ToString();                      
                                 }
                            }
                            catch (Exception ex)
                            {
                                MessageBox.Show("Fehler: Datei konnte nicht gelesen werden. Fehlermeldung: " + ex.Message);
                            }
                        }
            Wenn ich mit dem Programm eine Datei mit 30.000 Zeilen öffne, dann werden die Daten in ca. 2,3 sek. angezeigt. Bei der kompletten Datei (die aktuelle Datei hat 431.000 Zeilen) "hängt" das Programm mit "Keine Rückmeldung". Im Moment weiß ich nicht weiter

            Gruß,

            Karlo

            Comment


            • #7
              Die Dauer sollte eigentlich ungefähr linear ansteigen.

              Schonmal gecheckt ob dir nicht einfach der reale Hauptspeicher ausgeht und dein Rechner sich beim swappen des Hauptspeichers auf die Platte austobt?
              Immerhin kopierst du einfach mal so ein Array von 400000 Strings im Speicher rum.

              So wie du das gemacht hast kannst du das laden eh durch File.ReadAllLines ersetzen und kopieren in ein Array sparen.

              Comment


              • #8
                Wer soll eigentlich 431TDS Zeilen auf dem Bildschirm bearbeiten?
                Wie lange ist die Wartezeit des neueinlesen nach einem filtern? Spätestens da wird dir der Hauptspeicher knapp werden, wenn du das Array umkopieren willst, ein Extract daraus ziehen o.a. Rechne das mal durch, wieviel Speicher benötigt wird, wenn je Zeile nur 10 Zeichen enthalten sind

                So ist das m.E. nicht sinnvoll umzusetzen.

                Soll die Datei nur betrachtet werden, lies sie in Blöcken a 200 Zeilen ein und zeige diese an. Für das bearbeiten wird man wohl ein andere Lösung suchen müssen. Man könnte - neben einer DB-Lösung - auch die Datei vorher bearbeiten und gefilterte Auszüge vorab speichern o.ä. Hat jede Zeile der Datei die gleiche Länge, kann man suchen, filtern u.a. direkt mit der Datei ohne DB realisieren
                Zuletzt editiert von Christian Marquardt; 10.01.2012, 14:00. Reason: Rechtschreibung
                Christian

                Comment


                • #9
                  Die genannten Schlagworte Listview und VirtualMode könnten bereits weiterhelfen: http://www.codeproject.com/KB/miscctrl/hplv.aspx
                  MfG
                  Cheat-Sheets for Developers / Programming Quotes

                  Comment


                  • #10
                    es müssen nur so viele Zeilen angezeigt werden, wie die Textbox hoch ist, z.B. 100 Zeilen.

                    Die Datei in eine List<string> myList einlesen.

                    Abfragen auf myList durchführen und das Ergebnis in einer Ergebnisliste halten und auch von dieser nicht mehr als 100 Zeilen anzeigen.

                    Mit den beiden Bildlauftasten kann man die angezeigten Zeilen in der ListBox bestimen.

                    Z.B. BildNachOben => falls nicht am Listenanfang wird der Listenindex um 50 vermindert.

                    BildNachUnten => falls nicht am Ende der Liste, wird der Listenindex um 50 erhöht.

                    angezeigt werden die Listeneinträge Listenindex bis Listenindex + 100 in dem man diese in die ListBox mit (myListBox.Items.Clear() und myListBox.Items.AddRange() einliest.

                    Comment

                    Working...
                    X