Toon posts:

[c++] omslachtig tekstbestand bewerken

Pagina: 1
Acties:

Verwijderd

Topicstarter
Hallo, ik ben op dit moment heel omslachtig bezig met het bewerken van bestanden in c++ versie 1.52 (ja een hele oude)

Wat doe ik in een tekstbestand:
- zoeken naar een record
- bij een gevonden record het bijbehoren aantal verhogen (dus wijzigen)
- een record verwijderen
- een record toevoegen (niet onderaan het bestand, bestand is op gesorteerd)

Op dit moment ga ik als volgt te werk:
1 maak gebruik van 2 bestanden,
bestand 1 lees ik en zoek ik in
bestand 2 schrijf ik in (alle records - verwijderde records + gewijzigde aantallen)

vervolgens overschrijf ik bestand 1 met bestand 2 en kan weer verder gaan.

Dit is natuurlijk een hele trage manier van werken, in de toekomst zal het tekstbestand meer dan 10.000 records bevatten waardoor het alleen maar langzamer wordt.

Hoe kan ik het bestand op een andere manier werken, zodat ik maar in 1 bestand bezig ben

  • _Squatt_
  • Registratie: Oktober 2000
  • Niet online
Je kunt toch gewoon in een fstream seeken om bij een record dat gewijzigd moet worden te komen. En nieuwe records kun je invoegen, nadat je alle records er achter hebt opgeschoven.

Maar als het uiteindelijk 10.000 records moet gaan bevatten, lijkt me dat je dat misschien beter met een database op kunt lossen.

"He took a duck in the face at two hundred and fifty knots."


Verwijderd

Topicstarter
kun je misschien iets specifieker zijn met het schuiven van records?

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 21-08 17:14
Hoe vreemd het moge lijken, je oplossing is toch de netste en meest correcte. Een database kan hetzelfde doordat ze een ander opslag mechanisme gebruiken dan tekst files.

Als snelheid een issue is dan is een upgrade naar Win32/Vc7 waarschijnlijk de makkelijkere oplossing. Dat maakt het ook veel makkelijker om geavanceerde datastructuren te gebruiken. In Win16 een cache implementeren is :X

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • _Squatt_
  • Registratie: Oktober 2000
  • Niet online
Verwijderd schreef op 03 April 2003 @ 12:20:
kun je misschien iets specifieker zijn met het schuiven van records?
Nou, een heel simpel voorbeeld:

Je hebt een file met 3 records: [a][c][d]
Nu willen we [b] achter [a] invoegen. Dan lezen we [d], en schrijven we dat aan het eind: [a][c][d][d]
Dan lezen we [c] en scrijven dat er net achter: [a][c][c][d]
Nu hebben we ruimte voor [b]: [a][b][c][d]

Dit is echter niet zo efficient, je zou bijvoorbeeld meerdere records tegelijk kunnen lezen en schrijven.

[ Voor 19% gewijzigd door _Squatt_ op 03-04-2003 12:35 ]

"He took a duck in the face at two hundred and fifty knots."


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 22-08 01:56
Het is de vraag hoe ingewikkeld je het wel maken. Als de performance die je ervaart nog acceptabel is, kun je je huidige methode aanpassen door 'in place' records te verwijderen. Als kan al precies zoals je het nu doet, maar dan door in hetzelfde bestand te werken. Het is geen enkel probleem dat je in hetzelfde bestand leest en schrijft, zolang je de te lezen informatie niet vroegtijd overschrijft. Zoals jij het nu doet, gebeurt dat niet, dus gaat 't goed.

Als je een veel geavanceerdere manier zoekt om gegevens op te slaan, zou je eens een andere datastructuur kunnen proberen. Voor het opslaan van geordende records op harde schijf zijn B-trees een veelgebruikte datastructuur.

Verwijderd

Topicstarter
nou ik ga voor de eerste optie, om ongeveer zo door te gaan als nu, alleen kom ik er dus achter dat er een betere manier is om te lezen en schrijven in het zelfde bestand. Ik doe op dit moment
fread = fopen("bron.txt",r)
fwrite = fopen("temp.txt",w)

op welke manier kan ik dan tegelijk lezen en schrijven, mits...

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 22-08 01:56
Lezen en schrijven?
C:
1
fp = fopen("bron.txt", "r+t");

Maar dat had je zelf ook allang in de manual gevonden natuurlijk.

  • riezebosch
  • Registratie: Oktober 2001
  • Laatst online: 21-06 17:10
C++:
1
fstream file("file.txt", ios::binary | ios::in | ios::out);


weet niet of deze manier anders/beter is dan die je nu gebruikt, maar op deze manier kan je iig wel met Random File Acces de read/write pointer willekeurig door je bestand bewegen.

[ Voor 8% gewijzigd door riezebosch op 03-04-2003 14:33 ]

Canon EOS 400D + 18-55mm F3.5-5.6 + 50mm F1.8 II + 24-105 F4L + 430EX Speedlite + Crumpler Pretty Boy Back Pack


Verwijderd

Topicstarter
Soultaker schreef op 03 april 2003 @ 13:20:
Lezen en schrijven?
C:
1
fp = fopen("bron.txt", "r+t");

Maar dat had je zelf ook allang in de manual gevonden natuurlijk.
nou nee dit had ik nog niet gevonden (wel goed gezocht), en dit geeft voor mij weer een nieuwe ingang om verder te gaan.

Verwijderd

Je kan ook gebruik maken van een index. Dit kan je bijvoorbeeld doen door in de 1e file op te slaan op welke positie in de 2e file het record staat. Het voorbeeld van _Squatt_ wordt dan:

De data file bevat [a][c][d]

index file bevat het volgnummer van het record en de startpositie in de data file. Dus:
'a' 0
'c' 100
'd' 200

Record b toevoegen:
data file: [a][c][d][b]
Aan de index file voeg je 'b' toe:
'a' 0
'c' 100
'd' 200
'b' 300
De indexfile kan je in z'n geheel in geheugen houden (linked list oid) en hoef je daarom ook niet in volgorde te houden. Het inlezen van een record kan heel snel:
file openen, filepointer verhogen met startpositie voor record, data lezen.
Het schrijven gaat op dezelfde manier.

Een record verwijderen volstaat door het verwijderen van de entry uit de index file. De data staat dan nog wel in de data file, maar kan je niet meer benaderen omdat de werwijzing verdwenen is.

data:
[a][?][d][b]
index:
'a' 0
//met spaties overschreven regel
'd' 200
'b' 300

Als je nu weer een record wilt toevoegen kan deze in de data file worden gezet door [?] te overschrijven.
Aan de index voeg je gewoon weer een index achteraan toe. Deze zal dus na elke toevoeg actie groter worden, maar na elke verwijder actie niet kleiner! De indexfile kan je eens in de zoveel tijd weer opnieuw schrijven om de zaak weer op te schonen.


Ik ben er voor het gemak van uit gegaan dat elk record een vaste grootte heeft van 100 bytes. Als je dit mooier wilt doen moet je in elk record opslaan hoeveel bytes je record groot is. Je data file moet je dan opdelen in blokken. Als je data wilt toevoegen aan een record waardoor je buiten het blok zou moeten schrijven moet je het record naar achteren verplaatsen (of ergens tussenin waar wel genoeg ruimte is). Uiteraard moet je dan ook weer je indexfile aanpassen.

In jouw geval zou ik het lekker simpel houden en een vaste maximale grootte kiezen voor elk record. Later kan je het altijd nog uitbereiden naar records met variabele grootte als dat nodig blijkt te zijn.

Als dit idee je wat lijkt, maar je niet helemaal weet hoe je het moet doen, wil ik wel wat (pseudo) code posten.

succes

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 22-08 01:56
Verwijderd schreef op 04 April 2003 @ 09:30:
De indexfile kan je in z'n geheel in geheugen houden (linked list oid) en hoef je daarom ook niet in volgorde te houden.
Ja, dat is slim, dan heb je eindelijk toegang tot je gegevensbestand in constante tijd en dan moet je nog je index lineair doorzoeken om je gegevens te vinden. 8)7 Een betere suggestie zou een heap of een andere gesorteerde boomstructuur zijn.

Verder ben ik het trouwens wel met je verhaal eens, al weet ik niet zeker of het opgaat voor het probleem van de topic starter. Als het een echt tekstbestand is dat bewerkt moet worden (omdat het bestand door mensen gelezen wordt of met een andere bron uitgewisseld moet worden) dan is het misschien niet mogelijk om zomaar een apart indexbestand toe te voegen en verwijderde regels in het bestand te laten staan.

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 10:39

Janoz

Moderator Devschuur®

!litemod

Wat je ook kunt doen is (* Janoz slingert ff wat db technieken uit de mouw) in de eerste plaats zorgen dat je records allemaal even groot zijn. Tenzij je grote lappen tekst opslaat is dit erg efficient met bewerkingen. Het ene record past dan namelijk exact op de positie van een ander record, wat erg handig is bij het verplaatsten.

Verder is het handig om een wis bit toe te voegen aan elk record. Dit bitje geeft aan of het record op die plek al gewist is of nog gewoon bestaat. Hierdoor hoef je alleen een bitje om te zetten waneer je een record verwijderd.

Kijkt, waneer je een record invoegt, of er op de positie waar het record terecht moet komen misschien een gewist record staat wat overschreven kan worden. Als dit niet het geval is, schrijf het record dan weg achteraan een 2e bestand. Dit tweede bestand gebruik je om enkele records in op te slaan. Waeer je een record wist zou je dan bv kunnen kijken of een record uit het bestand hier kan. Als het 2e bestand echt te groot gaat worden (1% van je db oid??) dan rebuild en schuif je in je orginele bestand om te zorgen dat alles er weer tussen past.

Als je nu bij het aanmaken alvast zorgt dat er een redelijk wat ruimte tussen de records is (afhankelijk van het gebruik van de db, veel ruimte bij een applicatie waarin het aantal records alleen maar groeit) zal het aantal keren dat het 2e bestand moet worden ingevoegd in het 1e best meevallen.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 10:39

Janoz

Moderator Devschuur®

!litemod

Zo'n index bestand moet je eigenlijk vooral gebruiken bij:
1 variabele record lengten
2 opslaan van een alternative sortering

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Verwijderd

Soultaker schreef op 04 April 2003 @ 09:38:
[...]

Ja, dat is slim, dan heb je eindelijk toegang tot je gegevensbestand in constante tijd en dan moet je nog je index lineair doorzoeken om je gegevens te vinden. 8)7 Een betere suggestie zou een heap of een andere gesorteerde boomstructuur zijn.
stom... 8)7 8)7 Linear zoeken in een lijst met 10.000 entries gaat niet erg snel worden nee. Lineaire lijst moet boom worden natuurlijk.

Bedankt voor de verbetering
Pagina: 1