Archiv verlassen und diese Seite im Standarddesign anzeigen : QBASIC: Zeile aus Datei einlesen
Bemminger
05.05.2004, 19:13
Ich möchte eine Datei einlesen. Dabei will ich gezielt auf eine Zeile in der Datei zugreifen. Geht das mit LINE INPUT? Bis jetzt musste ich alle Zeilen vorweg einlesen um z.B. an Zeile 2300 ranzukommen. Geht das irgendwie direkt?
Bis jetzt mache ich das so:
OPEN "database.txt" FOR INPUT AS #1
LINE INPUT #1, line$
PRINT line$
Dann wird die erste Zeile ausgegeben. Wie komme ich direkt an Zeile 2300 ran?
Bis jetzt mache ich das so:
OPEN "database.txt" FOR INPUT AS #1
LINE INPUT #1, line$
PRINT line$
und das ist korrekt für eine sequentielle Datei.
Also für Zeile 2300:
for i = 1 to 2300 : line input #1, dummy$ : next i
eben 2300 mal in den Mülleimer lesen.
und dann die interessante Zeile lesen...:)
in einer Textverarbeitung bei "Cursor-down" macht der Computer auch nichts anderes. Und 2300 Zeilen Dummy-Read lässt den auch kalt. 1/100stel Sekunde vielleicht, das ist nix.
P.S. geht eher schneller auf heutigen PCs...
hellraiser
06.05.2004, 11:29
Wenn die Zeilen alle gleich lang sind (was sie ja wahrscheinlich nicht sind) könntest du über LEN die Recordlänge beim Öffnen der Datei angeben und dann binär lesen.
Vor dem lesen könntest du über SEEK (oder wie das in QB heisst) an den Record #2300 springen und dann einmal einlesen.
Wäre die zweite Variante für eine Flat-database, setzt allerdings eben voraus, dass jeder datensatz gleich lang ist.
Bemminger
06.05.2004, 12:09
Jo, mit 2300 mal in den Mülleimer lesen habe ich das bis jetzt auch gemacht. Das Programm ist allerdings für einen Uralt 386er Laptop. Die Wartezeit ist schon beträchlich bei 2300 Zeilen. Deswegen brauche ich irgendwie einen Direktzugriff.
Wie ist das mit SEEK? Die Zeilen sind zwar unterschiedlich lang, aber kann ich da nicht einfach pauschal 80 als Länge (worst case) annehmen?
hellraiser
06.05.2004, 13:06
nein. es funktionier nicht mit
SEEK #1, <ZEILENNUMMER>
sondern
SEEK #1, <RECORDNUMMER>
wenn du jetzt unterschiedlich lange records (=zeilen) hast, dann geht er bei
SEEK #1, 2300
nicht auf die 2300ste zeile sondern an das byte-offset 80*2300 = 184000
Also wenn du die textdatei selbst produzierst und die nicht von woanders herkommt würde ich an deiner stelle eine datei mit festen record längen produzieren.
Dann aber auch nicht mehr via "LINE INPUT" oder so sondern mit dem Befehlssatz:
OPEN BINARY
PUT
SEEK
GET
Ist das ímmer die gleiche Datei? (während eines Programmlaufs).
Dann könntest Du beim Programmstart z.B. einmalig 100 temporäre Dateien anlegen, also Zeile 1 bis 100, Zeile 101 bis 200 usw.
Das kratzt den Computer auch nicht sonderlich, verzögert halt den Programmstart um ein paar Sekunden***; Meldung ausgeben "bitte warten, erstelle Index" oder so.
Dann kannst du gezielt aus der Zeilennummer die jeweilige Datei öffnen, also bei 2300 --> sei jetzt eine Stringvariable Namens Zeilennummer$
open (left$(Zeilennummer$,2)+".tmp") for input as #1
jetzt nur maximal 99 mal Mülleimer lesen...
close #1
***Dafür rennt es dann während des Programmlaufs:)
Bemminger
06.05.2004, 19:55
Andreas, das ist ja genial einfach (oder einfach genial). Stimmt, ich könnte die Textdatei in kleine Päckchen aufteilen und habe dadurch wesentlich kürzere Zugriffszeiten. Warum bin ich darauf nicht selbst gekommen?
Was haltet ihr eigentlich von der Idee, die Datei zu öffnen und jede Zeile in eine String Variable abzulegen? So quasi als Textpuffer. Ich glaube aber das verbraucht wahrscheinlich zu viel Arbeitsspeicher, hm?
hellraiser
07.05.2004, 10:50
bist du bei meikro$oft angestellt? :rolleyes:
Bemminger
08.05.2004, 23:11
Ich bei Micro$chrott? Nein, warum? War das die Anspielung auf "640kB sind mehr als man je bräuchte"?
hellraiser
09.05.2004, 17:19
nein, war eine anspielung auf " Was haltet ihr eigentlich von der Idee, die Datei zu öffnen und jede Zeile in eine String Variable abzulegen?" :rolleyes:
Bemminger
10.05.2004, 01:01
Iist die Idee eher recht oder schlecht? Wäre doch von der Zugriffszeit die schnellste Variante, oder? Wird das laufen auf einem 386er mit 1 MB RAM?
hellraiser
10.05.2004, 10:10
klar ist das möglich. rechne es dir doch aus...
wenn du schnellste zugriffszeit willst:
array mit strings gleicher länge anlegen (länge mindestens die der maximalen länge einer dateizeile). dann diese länge multipliziert mit der anzahl der zeilen. soviel ram brauchst du.
mal nen kleinen tipp: dann kannst du genauso eine flat database als datei anlegen mit gleichen recordlängen. ist von der geschwindigkeit zwar ein bissel (wenig merkbar) langsamer aber du brauchst den krempel nicht komplett ins ram lesen.
@Hellraiser: Der Bemminger sollte sich mit just diesem Wissen jetzt schleunigst bei M$ bewerben. Vielleicht wirds ja dann mal ein fixes BS...
und was die Anzahl der temporären Dateien angeht:
Tipp an alls M$ Programmierer: Diese doch bitte auch wieder wegmachen; die sollen nur temporär sein und nicht wie bei mir und vielen anderen auch "TASRITIF"
"Terminate And Stay Resident In Temporary Internet Files"
(immer paartausend Mülldateien drin... - der User solls löschen:mad: )
hellraiser
13.05.2004, 13:53
LOOOL
btw: schonmal ins "temp" verzeichnis geschaut?
wenn du mal platz auf der platte brauchst kannst das auch noch leeren.
und wenn du ein multiuser betriebssystem (2k/xp) dann hast du mindestens 2 verschiedene temp verzeichnisse (von den unterschiedlichen temp internet files mal abgesehen ;)
Powered by vBulletin® Version 4.1.7 Copyright ©2012 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.