[Delphi] Bepaalde regel inlezen textfile

Pagina: 1
Acties:
  • 125 views sinds 30-01-2008
  • Reageer

  • Oscar Mopperkont
  • Registratie: Februari 2001
  • Laatst online: 03-08-2024
Ik ben een progje aan het maken dat eventueel ongelofelijk grote textfiles moet kunnen inlezen. Nu wil ik zo'n textfile niet in 1 keer in het geheugen hoeven te zetten, en de file in random volgorde inlezen.

Wat ik nu nodig heb is een manier waarbij ik kan zeggen lees regel x in. Dan kun je natuurlijk een loopje maken dat ie eerst x-1 readln's doet, en vervolgens de regel inleest naar de variabele waarje de waarde inzet. Maar dat komt denk ik de snelheid niet ten goede, en is natuurlijk erg omslachtig.

Is het dus niet gewoon mogelijk om te zeggen lees regel x in?

  • klinz
  • Registratie: Maart 2002
  • Laatst online: 21-05 09:01

klinz

weet van NIETS

Als alle regels dezelfde lengte hebben, is het mogelijk met een Seek(regellengte * regelnr, soFromBeginning). Is dat niet het geval, kun je misschien beter een indexfile aanmaken met de fileposities van het begin van elke regel.

  • Just_a_Gamer
  • Registratie: November 2001
  • Laatst online: 27-05 07:15
Je kan volgens mij beter TStringlist gebruiken, dan laadt de stringlist je text file in 1 keer in je geheugen. Je kan dan vervolgens zo per regel lezen bv:

Delphi:
1
2
3
4
5
6
7
8
9
10
11
var
  AStringList: TStringList;
begin
  AStringList := TStringList.Create;
  try
    AStringlist.LoadFromeFile( '<je tekstfile>' );
    AStringlist[ <RegelNummer> ];
  finally
    AStringList.Free
  end;
end;


Stringlist is vooral handig als je tekst file niet zo groot is :)

[ Voor 12% gewijzigd door Just_a_Gamer op 14-02-2004 13:05 ]


Verwijderd

Wat moet je dan doen met die ongelooflijk grote textfiles ? Misschien zijjn er handigere oplossingen voor je originele probleem ?

  • Oscar Mopperkont
  • Registratie: Februari 2001
  • Laatst online: 03-08-2024
Just_a_Gamer schreef op 14 februari 2004 @ 13:03:


Stringlist is vooral handig als je tekst file niet zo groot is :)
Daar had ik al over gelezen. Maar het probleem is dat het programma juist moet kunnen werken met files die te groot zijn om in het geheugen te zetten.

Ik vraag mijzelf ook af hoe groot zo;n file dan zal zijn. Maar ik moet dit voor een docent proggen en die gaf aan dat hij het zo wilde. Dus als hij het zo wil, dan kan hij het zo krijgen!

  • Just_a_Gamer
  • Registratie: November 2001
  • Laatst online: 27-05 07:15
Ik zou gewoon eerst voor de simpelheid gewoon stringlist gebruiken. Je kan later nog gewoon uitbreiden/verbeteren. Gewoon ff testen hoe je programma werkt als hij de tekstfile probeert in te lezen :) Hoe groot is die tekst file wel niet? Maar succes verder :)

  • Infinitive
  • Registratie: Maart 2001
  • Laatst online: 25-09-2023
Zoals al is voorgesteld, zou je d.m.v. indexering een eind kunnen komen:

Opmerking: ik ga er vanuit dat je de file dat altijd in binary mode benadert.

Als van de file nog geen index beschikbaar is, maak je deze eerst door van voor naar achter door je file heen te lopen en zodra je een newline tegenkomt (\r, \n of \r\n) append je de positie ("offset") aan je index-file (4 bytes per stuk). Voeg aan het begin de positie 0 (eerste regel) en aan het eind de de filelengte (1 positie verder dan laatste character) toe(z.g.n. sentinels).

Heb je van een file een index, dan kan je de i-e regel vinden door in je index de posities op te halen van waarde i-1 en i. Daar kan je direct naartoe jumpen. Vervolgens heb je nu de posities van het begin van je regel en het eind van je regel in de echte file. Dus nu kan je met een jump en een leesoperatie je regeltje ophalen.

Het nadeel is het maken van de index: dus tenzij je vaak in zo'n file moet zoeken heeft zo'n index maar weinig nut.

Ik kan me wel voorstellen dat je best grote van dit soort files kan hebben. Logfiles bijvoorbeeld. Maar dan nog: het doorzoeken van een 100 MB file in geheugen is echt niet zo'n probleem tegenwoordig...

[ Voor 16% gewijzigd door Infinitive op 14-02-2004 13:58 ]

putStr $ map (x -> chr $ round $ 21/2 * x^3 - 92 * x^2 + 503/2 * x - 105) [1..4]


Verwijderd

Verwijderd schreef op 14 februari 2004 @ 13:07:
Wat moet je dan doen met die ongelooflijk grote textfiles ? Misschien zijjn er handigere oplossingen voor je originele probleem ?
Ik wil bovenstaande vraag ff beantwoord hebben!

[ Voor 2% gewijzigd door Verwijderd op 14-02-2004 21:07 . Reden: spelling ]


  • alienfruit
  • Registratie: Maart 2003
  • Laatst online: 26-05 11:18

alienfruit

the alien you never expected

Je zou een tekst parser kunnen schrijven :)
Als ik het goed herinner kun je dan wel max 25mb/s halen qua parser snelheid (bij een Delphi Parser) maar lijkt me toch wel snel genoeg?

  • Tomatoman
  • Registratie: November 2000
  • Nu online

Tomatoman

Fulltime prutser

Hoe herkent een willekeurig mechanisme waar regel n is gepositioneerd? Door te zoeken naar de eerste regel die volgt op het (n -1)de regeleinde. Het is simpelweg onmogelijk om de nde regel te vinden zonder het document vanaf het begin te parsen.

Ik vrees dat handwerk is geboden. Je zou gebruik kunnen maken van een memory mapped file, zodat Windows zelf kan bepalen welke delen van het bestand daadwerkelijk in het geheugen worden gelaten. Vanuit het oogpunt van geheugenbeheer is dat de beste - en efficiëntste - oplossing.

Om het nog wat ingewikkelder te maken zijn er tenminste drie mogelijkheden voor de markering van een regeleinde: dat kan met de karakters CR (carriage return - #13), LF (line feed - #10) en ook met CR direct gevolgd door LF (#13#10). Je zult om de nde regel te vinden net zolang moeten zoeken totdat je (n - 1) van deze regeleinden bent tegengekomen. Daarna kun je eenvoudigweg een stuk tekst uit de memory mapped file in het geheugen streamen.

Een snellere manier kan ik helaas niet verzinnen.

Een goede grap mag vrienden kosten.


  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Of gewoon lezen in blokken van een paar meg, regels tellen, volgende paar meg lezen net zo lang tot je de juiste regel te pakken hebt....

Deze draad bevat een gelijksoortig probleem. Ik heb de code helaas niet meer online staan die ik toen postte, maar ik ga even voor je graven. Het is dan wel VB, maar als je het kunt "lezen" heb je 't zo omgeschreven naar Delphi. Verder is het easy om precies op jouw probleem aan te passen. Dus: Blok lezen, splitten op enters, array-size van je split = aantal regels, optellen bij totaal, juiste blok? Nee? -> Opnieuw blok lezen. Ja? -> Juiste regel lezen.

edit:

Code staat, onder de originele link, weer online.


Disclaimer: Mocht je hier iets mee willen gaan doen, zorg dan wel dat je de betreffende draad effe goed leest!

[ Voor 40% gewijzigd door RobIII op 15-02-2004 04:43 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij

Pagina: 1