C# nagy méretű szövegfájl

C# nagy méretű szövegfájl
2019-02-14T10:30:38+01:00
2019-03-18T10:22:13+01:00
2022-10-15T21:31:17+02:00
pfhu
Sziasztok!

Nagy méretű szövegfájlt szeretnék megjeleníteni a programban (C#,WinForms).
Nagy méret alatt 10 000 sor nagyságrendet értek.
Mondjuk 40 000 sor esetén 8 MB méret. Egyszerű log fájlokról van szó.

ListBox vagy ListView-ban gondolkodtam eddig, de egy richtextbox is jó lenne. Viszont a fapados megoldásommal mindegyik lassú.

Pl.: string[] ->File.ReadAllLines majd feltölteni foreach-el a szöveget.

Ha feltöltődött, utána nem lassú, kezelhető marad a control csak amíg feltölti az borzasztó lassú.

Milyen gyors és okos megoldás létezik erre?

Köszönöm.
Mutasd a teljes hozzászólást!
Legegyszerűbb, legrövidebb megoldás:
ListView1.Columns.Add("Bejegyzes") ListView1.View = View.Details Dim adatlista As New List(Of ListViewItem) Using sr As New StreamReader("c:\alma.txt") Dim szoveg As String = sr.ReadToEnd() For Each r In szoveg.Split(vbCrLf) adatlista.Add(New ListViewItem(r)) Next End Using ListView1.Items.AddRange(adatlista.ToArray)
450 000 sor, 30MB és 1 másodperc alatt lefut.

k_attis megoldása ennél szebb és jobb, viszont az némileg hosszabb forráskód és némileg bonyolultabb.
Mutasd a teljes hozzászólást!

  • Szvsz ez elég gyors kéne, hogy legyen:

    // listView, fileName inicializálás // ... using (StreamReader reader = File.OpenText(fileName)) { string line = String.Empty; while ((line = reader.ReadLine()) != null) { ListViewItem item = new ListViewItem(); // line parseolása, stb. // item.SubItems.Add(...); listView.Items.Add(item); } }
    Mutasd a teljes hozzászólást!
  • Szerintem a leggyorsabb a StringBuilder használata ilyen nagy méretű szövegeknél.

    RichTextBox rtxBox = new RichTextBox(); StringBuilder sb = new StringBuilder(); using (StreamReader reader = File.OpenText(fileName)) { string line = String.Empty; while ((line = reader.ReadLine()) != null) {sb.Append(line);} } rtxBox.Text = sb.ToString;
    Mutasd a teljes hozzászólást!
  • rtxBox.Text = File.ReadAllText(path) Vagy ReadAllLines, és Pl. datagridview virtuálisra állítva. De az is megoldás, hogy nem a fõszálon olvasod be a szöveget, hanem indítasz egy új taskot, és ha befejezõdik akkor töltöd fel amit fel akarsz.
    Mutasd a teljes hozzászólást!
  • 1. Szerintem nézd meg valamilyen toolal, hogy mi a lassú, mert azt kell optimalizálni, ha egyáltalán lehet.
    2. Ne UI szálon töltögess file-okat, hanem háttérszálon (+dispatch).
    3. Ne egyesével adogass a control tartalmához sorokat, hanem egy lépésben, ahogy ezt már páran javasolták.
    Mutasd a teljes hozzászólást!
  • Ha fel kell dolgozni a sorokat bármilyen módon, akkor sajnos a ReadAllText nem játszik...
    Ha Log, akkor lehet valamilyen eseményt, dátumot, felhasználót, vagy bármit színezni akar... vagy nem :D nem írta.
    Mutasd a teljes hozzászólást!
  • Egy lépéses megoldással ugyan az történik mint ha foreach-ben add-olom: percekig tart amíg végez. Vagy nem látszik semmi, csak a végén, vagy (megoldás-függő) megjelenik a scroll bar oldalt ami ha legörgetem elkezd mászni felfele.

    Nem a fájl beolvasása a lassú, hanem amíg feltölti az adott controlt, teljesen mindegy hogy melyik és hány lépésben. Background workert próbáltam, azzal is ugyan az a helyzet, a különbség csak annyi, hogy a gui nyomkodható marad közben.

    Ezt a bejegyzést találtam: 
    https://social.msdn.microsoft.com/Forums/windows/en-US/e0d66251-7b3c..64 000 elemet 2-3 mp alatt hozzáadja neki. Nekem pont ez a gond, hogy ez tart percekig. Kipróbáltam a listbox.addRange-t, de azzal is ugyan az a helyzet.
    Mutasd a teljes hozzászólást!
  • Mi történik, ha a feltöltés idejére explicit eltűnteted a kontrollt? Ezt a linkelt topikban többen is javasolták, de nem úgy tűnik, hogy a kérdező kipróbálta volna.
    Mutasd a teljes hozzászólást!
  • Nem segít. Tehát maga a control feltöltés az ami lassú.
    Mutasd a teljes hozzászólást!
  • És ha DataSource-t használsz?
    Nem próbáltam, lehet, hogy nem is működik.
    De egy próbát megérne.

    Ezt a példát találtam: BindingSource Class (System.Windows.Forms)
    Mutasd a teljes hozzászólást!
  • a richtextboxot amit irtam kipróbáltad?
    vagy mindenképpen listviewt akarsz? mert az első hsz ben még richtextbox is játszott...

    ha mindenképpen listview kell, akkor az semmiképpen nem jó, ha for eachel adod hozzá
    az elemeket...
    c# kódom nincs, nekem vb.net ben ez van feltöltésre, és 100k elemet 3 sec alatt tölt be:

    Dim itms As New List(Of ListViewItem) For each OneLine As String in AllLines itms.Add(new ListViewItem(OneLine)) Next ListView1.BeginUpdate ListView1.Items.AddRange(itms.ToArray()) ListView1.EndUpdate
    Mutasd a teljes hozzászólást!
  • És ha seek-elnél a fájlban?
    Nem tudom C#-ban hogy van a fájl olvasás, illetve pontosan milyen céllal nyitnád meg, de ha olvasni kell belőle szöveget (mármint a monitorról), akkor esetleg elég annyi szöveget kiolvasni belőle, ami 1-2 oldalra elég, aztán csak változtatod a pozíciót. Szóval egyszerre mindig csak kis részeket olvasol ki.
    Mutasd a teljes hozzászólást!
  • Hogy itt mennyi amatőr megoldást posztoltak eszem megáll.

    a 8MB-os állományt elég vicces nagy méretnek nevezni.

    Azért lassú az egész mert:
    1: minden nyünyü sornál rángatod az egész oprendszert hogy átemelje az adatokat háttértárról a memóriába (ugyan van bufferje de akkor is)
    2: beledolgozod a sorokat listaelemként a  memórába ami jóval több helyet foglal mint egyébként kellene (magyarul egyszer betöltöd a memóriába aztán átkonvertálod más formába a memóriába)

    Megoldás:
    1: emeld be az egész fájlt memóriába (pl.:memorystream) és onnan elemezd
    2: ne hozz létre listaelemeket, hanem használd a listview-t virtuális módban, ez egy jól bevált módszer kb a rómaiak óta

    +1: a két módszert ötvözd, ne transzformáld át az adatokat hanem hozz létre egy listát amiben csak azt tárolod, hogy a fájl kezdetétől számítva honnan kezdődnek a sorok, esetleg azzal kiegészítheted hogy akkor most ez warning, error, info, debug stb súlyosságú logbejegyzés, esetleg még az idejét is hozzácsaphatod
    A Listview virtuális módban annyit fog tenni hogy csak a képernyőn látható elemek tartalmát kéri, amit az elkészített lookup listád alapján SEEK-elve ki tudsz kapni a memóriából és oda tudod adni a Listview-nak.

    Ennyike.
    Mutasd a teljes hozzászólást!
  • Legegyszerűbb, legrövidebb megoldás:
    ListView1.Columns.Add("Bejegyzes") ListView1.View = View.Details Dim adatlista As New List(Of ListViewItem) Using sr As New StreamReader("c:\alma.txt") Dim szoveg As String = sr.ReadToEnd() For Each r In szoveg.Split(vbCrLf) adatlista.Add(New ListViewItem(r)) Next End Using ListView1.Items.AddRange(adatlista.ToArray)
    450 000 sor, 30MB és 1 másodperc alatt lefut.

    k_attis megoldása ennél szebb és jobb, viszont az némileg hosszabb forráskód és némileg bonyolultabb.
    Mutasd a teljes hozzászólást!
  • én ugyanezt írtam pár hszel feljebb...
    Mutasd a teljes hozzászólást!
  • Csak most tudtam foglalkozni a kérdéssel.

    A legtöbb megoldás ugyan olyan lassan működött, mindegy hogy csak egy soros a fájlbeolvasás vagy hogy egy sorban (AddRange) lett hozzáadva. Mindegyik hosszú ideig tartott (10-20mp).

    k_attis megoldása nagyon profin hangzik, talán pont emiatt meghaladja a tudásom, így most ellenőrizni sem tudom.

    Zsergita válasza segített, de nem (vagy nem teljesen) amiatt, amire Csimbi is hivatkozott, mivel 

    ListView1.Columns.Add("Bejegyzes") ListView1.View = View.Details A fenti sorok nélkül Zsergita megoldása is lassú. Talán a Details view oldja meg? Mindenkinek köszönöm a válaszát.
    Mutasd a teljes hozzászólást!
Tetszett amit olvastál? Szeretnél a jövőben is értesülni a hasonló érdekességekről?
abcd