Results 1 to 15 of 15

Thread: Grote tekstbestanden snel inlezen

  1. #1
    John Kuiper
    Join Date
    Apr 2007
    Location
    Almere
    Posts
    8,747

    Grote tekstbestanden snel inlezen

    Ik gebruik al jaren deze code om grote tekstbestanden in te lezen
    Delphi Code:
    1. var FTextFile : TextFile;
    2. begin
    3.   try
    4.     Assignfile(FTextFile, aFileName);
    5.     reset(fTextfile);
    6.     while not eof(FTextfile) do
    7.     begin
    8.  
    9.  
    10.     end;
    11.   finally
    12.     close(ftextfile)
    13.   end;
    Maar is dat nog wel van deze tijd? Zijn er inmiddels geen betere manieren om een (heel groot) tekstbestand in te lezen.
    TStringlist is geen optie, omdat deze een restrictie heeft met een aantal regels (zover ik van het verleden weet).
    Delphi is great. Lazarus is more powerfull

  2. #2
    Quote Originally Posted by jkuiper View Post
    TStringlist is geen optie, omdat deze een restrictie heeft met een aantal regels (zover ik van het verleden weet).
    Je hebt niet voldoende aan 134,217,728 regels?

    Wat ben je van plan met de regels te doen? Alleen parsen/lezen of moet je ze ook in je geheugen opslaan?
    Want je kunt natuurlijk gewoon een complete buffer-blockread doen.

    In geval van AssignFile(Text) zou ik sowieso met SetTextBuf de buffer wat groter zetten (standaard 128).
    Maar je kunt ook TStreamReader gebruiken.

  3. #3
    Denk dat het er ook aan ligt wat je wilt doen tijdens het inlezen. Voordeel van jouw aanpak is dat je al meteen de informatie van delen van je bestand beschikbaar hebt, bijvoorbeeld voor een parse actie.

    We hebben toch ook de filestream beschikbaar?

    Hoe groot zijn grote tekstbestanden?

  4. #4
    Quote Originally Posted by Benno View Post
    We hebben toch ook de filestream beschikbaar?
    TStreamReader is een TTextReader die ook werkt met een FileStream.
    Maar heeft als extra voordeel dat je gewoon ReadLn e.d. kunt gebruiken.
    (Het is een Wrapper-class die een TStream gebruikt)

    Het kan soms zelfs handig zijn beide te gebruiken.
    Omdat TStringList bij LoadFromFile eerst alles in memory leest voordat het naar de strings gaat, kan het wel eens zijn dat dat nét teveel van het goede is. Je kunt dan bijvoorbeeld een TStreamReader gebruiken als tussenoplossing om de strings van een TStringList te vullen.

    Delphi Code:
    1. //MyStringList.LoadFromFile(filename);
    2. Reader := TStreamReader.Create(filename, true);
    3. try
    4.   MyStringList.BeginUpdate;
    5.   try
    6.     MyStringList.Clear;
    7.     while not Reader.EndOfStream do
    8.       MyStringList.Add(Reader.ReadLine);
    9.   finally
    10.     MyStringList.EndUpdate;
    11.   end;
    12. finally
    13.   Reader.Free;
    14. end;
    Zie ook https://stackoverflow.com/a/27008177/1037511

  5. #5
    John Kuiper
    Join Date
    Apr 2007
    Location
    Almere
    Posts
    8,747
    Wat ik al eerder zei: "in het verleden heb ik incidenteel problemen gehad met het inlezen van een bestand via TStringlist (weet alleen niet meer welke D versie het was)".
    Deze bestanden zijn matrices vanuit onze logistiek applicatie, die verwerkt worden in een memtable.

    Maar als de grootte van een TStringlist (flink) is uitgebreid, dan heb ik niets meer te vrezen en kan verder gaan met TStringlist. Uiteindelijk is het alleen lezen en verwerken.
    Delphi is great. Lazarus is more powerfull

  6. #6
    En als je je zorgen maakt over de TStringList dan kun je dus ook gewoon die TStreamReader.ReadLn gebruiken. En dan dus direct de getallen parsen naar je MemTable.

  7. #7
    mov rax,marcov; push rax marcov's Avatar
    Join Date
    Apr 2004
    Location
    Ehv, Nl
    Posts
    10,357
    De details:

    TStringlist is vrij traag en gebruikt de dubbel hoeveelheid geheugen (een om het als string te lezen en dan wordt die geassigned aan text die het nog eens gesplitst naar regel). Dat is overigens in 32-bit apps ernstiger dan in 64-bit apps. Bij een batch gebruik valt het nog wel mee, maar in een langer lopende applicatie is vaak simpelweg geen groot genoeg blok meer vrij.

    Een ander issue is echter gesorteerde tstringlists. Dat is tergend traag voor >50duizend tot enkele honderdduizenden regels afhankelijk van je pijngrens.

    Ik zit ook met dit probleem. Recentelijk heb ik wat oude D2006 binaries moeten compileren en de DXE binaries zijn veel en veel trager (waarschijnlijk de conversie overhead), deze werken met textfiles die door de jaren heen 100MB zijn geworden. Ik zie daarom van textfiles af als permanent storage formaat.

    IOW als je een grote textfile twee keer inleest, dan doe je wat fout. Op dit moment werk ik af en toe aan een generieke klasse met een instelbare blokgrootte. Ieder blok bevat een array of byte met nul terminated strings, en een index. Maar echt resultaten heb ik er nog niet van.

  8. #8
    Stijn Sanders develyoy's Avatar
    Join Date
    Jun 2008
    Location
    GentBrugge, Belgi?½
    Posts
    1,046
    Als het over zo veel data gaat zou ik tegenwoordig echt snel al naar SQLite kijken en de data in een tabel bijhouden.

  9. #9
    John Kuiper
    Join Date
    Apr 2007
    Location
    Almere
    Posts
    8,747
    Maar die data komt vanuit een ander systeem, die alleen maar tekst kan leveren. Dus dat gaat niet op
    Delphi is great. Lazarus is more powerfull

  10. #10
    Stijn Sanders develyoy's Avatar
    Join Date
    Jun 2008
    Location
    GentBrugge, Belgi?½
    Posts
    1,046
    Precies, het komt uit een ander systeem. Als het om opslaan van die gegevens gaat, zou ik niet kiezen voor een tekst bestand. In plaats van een gigantisch blok data telkens te laten en te verwerken, doe je dat 1 keer en kan je met de SQL engine sneller zoeken, sorteren, indexeren... Om zelf van niets extra afhankelijk te zijn heb ik deze gemaakt: https://github.com/stijnsanders/TSQLite

  11. #11
    John Kuiper
    Join Date
    Apr 2007
    Location
    Almere
    Posts
    8,747
    Ik snap je niet helemaal. De tekstbestand word geparset en in een memdataset geplaatst. Programma werkt razendsnel.
    Delphi is great. Lazarus is more powerfull

  12. #12
    mov rax,marcov; push rax marcov's Avatar
    Join Date
    Apr 2004
    Location
    Ehv, Nl
    Posts
    10,357
    develyoy: sqlite (of welke db dan ook) is alleen maar vertragend als operaties zeer grote delen van de data raken. Dat is nu net de reden ze te preloaden in memory ;_)

  13. #13
    Best kans dat ze in het gebruik sneller is dan zelf van schijf bufferen en efficient qua geheugengebruik dan een stringlist, omdat je eigen implementatie vaak de neiging zal hebben wat naïef of kort door de bocht te zijn.

    Niet dat ik SQLite zou gebruiken. Ik zou zelf wat bouwen, maar ja, ik ben dan ook naïef.
    1+1=b

  14. #14
    John Kuiper
    Join Date
    Apr 2007
    Location
    Almere
    Posts
    8,747
    Quote Originally Posted by GolezTrol View Post
    Ik zou zelf wat bouwen, maar ja, ik ben dan ook naïef.
    +1
    Delphi is great. Lazarus is more powerfull

  15. #15
    mov rax,marcov; push rax marcov's Avatar
    Join Date
    Apr 2004
    Location
    Ehv, Nl
    Posts
    10,357
    Ik denk niet dat sqllite echt default sneller zal zijn. Er zit met tabeldefinitie, encoding, collation e.d. toch een aardige setje abstractie lagen overheen dat je niet 1-2-3 wegpoetst.

    Aan de andere kant doet D2009 ook encoding conversie.

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •