Datenkreislauf – Die sequentielle Datenspeicherung
Als es noch keine Diskettenlaufwerke gab, standen lediglich Bandgeräte zur Datenspeicherung zur Verfügung. Und auf Bändern ist nur sequentielles Speichern möglich. Auch mit der Floppy kann man Daten sequentiell speichern, obwohl der Vorteil der Diskette, der direkte Zugriff auf Daten, nicht ausgenutzt wird.
Wenn Sie sich das Diskettenlaufwerk gerade erst gekauft haben, werden Sie sicher zu Beginn einige Schwierigkeiten haben, es auch richtig einzusetzen. Das erste, was man macht, wird das Laden und Abspeichern von Programmen sein. Daß Sie mit der Floppy noch viel mehr machen können, wissen Sie ja auch schon längst. Und sicher fallen Ihnen einige Möglichkeiten ein, die Sie wohl gerne realisieren möchten. Meistens sind das am Anfang eine Adressenkartei, eine Schallplattensammlung erfassen oder etwa seine Dias ordnen und auswerten. Wir möchten Ihnen den Einstieg etwas erleichtern und Sie Schritt für Schritt mit den Methoden der Datenverwaltung vertraut machen.
Es gibt verschiedene Arten von Dateien und unterschiedliche Methoden ihrer Verwaltung. Hauptsächlich sind das die sequentielle, die relative Datei und der Direktzugriff auf die Diskette.
Gerade für Anfänger ist die sequentielle Datei eine geeignete Methode, Daten zu verwalten. Diese Einfachheit ist allerdings verbunden mit einer gewissen Langsamkeit. Aber wenn sie sich erst einmal mit der sequentiellen Datenspeicherung auskennen, wird auch die relative Datei und die Direktzugriffsmethode kein großes Problem mehr für Sie darstellen. Außerdem gibt es genügend Probleme, für die eine sequentielle Datenspeicherung völlig ausreichend ist.
Zuerst sollen Sie einige wichtige Begriffe kennenlernen.
Sequentiell bedeutet hintereinander. Also alle Daten, die wir benutzen, werden hintereinander, sequentiell auf der Diskette gespeichert (bei Kassetten ist eine andere Methode gar nicht möglich).
Immer, wenn man von und über Dateien spricht, werden solche Vokabeln wie FELD, DATENSATZ oder auch RECORDS genannt. Was ist das eigentlich?
Der Computer ersetzt Karteikarten
Die meisten von Ihnen kennen eine Karteikarte. Auf dieser Karteikarte können mehrere Eintragungen stehen. Angenommen, Sie besitzen eine Adressenkartei, dann stehen auf jeder Karteikarte normalerweise der Vorname, Nachname, Straße, Postleitzahl und Ort und die Telefonnummer, manchmal auch der Geburtstag und andere wichtige Daten. Das sind die einzelnen Felder eines Datensatzes. Die Gesamtheit aller Felder auf einer Karteikarte bezeichnet man als einen Datensatz, also alle Daten, die zusammengehören. Somit besteht ein Datensatz aus mehreren Feldern. Und der Begriff Record ist nur die englische Bezeichnung für Datensatz. Alle Karteikarten, also alle Datensätze, nennt man eine Datei. Damit wären die wichtigsten Begriffe geklärt und wir können zum Wesen der sequentiellen Datei kommen.
Wie schon gesagt, werden bei dieser Dateiart alle Daten hintereinander (sequentiell) auf der Diskette gespeichert. Das sieht dann zum Beispiel so aus wie in Bild 1.

Angenommen, unsere Datei besitzt schon 200 Adressen und eine Adresse enthält den Namen Huber,Anton. Wollen wir jetzt seine Anschrift wissen, so muß die Datei von Anfang an durchsucht werden, bis zu dem Datensatz, in der der Huber steht. Steht der gesuchte Name ziemlich am Ende der Datei, so kann die Suche einige Zeit in Anspruch nehmen; je größer die Datei, desto mehr Zeit beansprucht die Suche. Diese Suche, aber auch alle anderen Operationen wie Ergänzungen, Veränderungen oder Sortieren der Datei spielen sich im Speicher des Computers ab. Das bedeutet, daß, wenn man mit dieser Adressendatei arbeiten will, zuerst die gesamte Datei von der Diskette in den Speicher geladen werden muß. Und am Ende, nach getaner Arbeit, wird sie wieder auf die Diskette zurückgespeichert.
Wenden wir uns dem Beispiel in Bild 2 zu. Es ist ein kleines und noch nicht einmal fertiges Adressen-Datei-Programm (die Funktionen »Suchen«, »Löschen« und »Ändern«) sind noch nicht codiert worden. Jedoch kann sich jeder dieser Module selber schreiben. Auf eine Besonderheit möchte ich gleich hinweisen. In den Zeilen 133 bis 135 stehen die Erklärungen der verwendeten Steuerzeichen, die diesmal codiert ausgedruckt wurden. Deswegen brauchen Sie nicht mehr mit der Lupe und viel Fantasie, die manchmal schwierig zu erkennenden Commodore-Steuerzeichen versuchen, zu interpretieren. Drücken Sie einfach die entsprechende Cursortaste (innerhalb der PRINT-Anweisung) wenn die Zeichen »CRR« und »CRL« im Listing erscheinen. Auf Ihrem Bildschirm sollten sie dann die entsprechenden Grafikzeichen erkennen. Gefällt Ihnen diese Art der Darstellung? Wir würden gerne Ihre Meinung dazu erfahren.
Der Aufbau des Programms dürfte nicht schwer zu durchblicken sein. Aber es gibt einige Programmzeilen und -abschnitte, die man sich einmal näher anschauen sollte.
Zeile 9110: Die Variable ST ist eine Statusvariable, die der C 64 und der VC 20 für sich beanspruchen. Hier gibt sie Auskunft darüber, ob das Dateiende erreicht ist. In diesem Fall wird nämlich das 6. Bit gesetzt (2 hoch 6 ergibt 64). Da aber in dieser Systemvariablen auch andere Nachrichten abgelegt werden, die andere Bits beeinflussen und ST auch bei Dateiende einen von 64 ungleichen Wert zuweisen können, müssen wir mit der AND-Verknüpfung feststellen, ob speziell dieses 6. Bit gesetzt ist.
Aus Sicherheitsgründen habe ich vor jedem OPEN-Befehl ein CLOSE gesetzt, damit nicht durch einen Programmierfehler ein »FILE OPEN ERROR» entstehen kann. Zum CLOSE-Befehl sei noch so viel gesagt, daß er unbedingt existieren muß. Sonst kann es vorkommen, daß nicht alle Daten auf die Diskette übertragen werden, und noch schlimmer, daß die Datei nicht ordnungsgemäß geschlossen werden kann. Dadurch kann die gesamte Datei unrettbar verloren sein. Also Vorsicht.
Wenn Sie sich das Programm etwas näher anschauen, könnten Sie über die Variablen »SS« und »L« stolpern. Diese Variablen habe ich eingesetzt als »Flags«. Sie regeln, ob ein Aufruf dieses Menüpunktes sinnvoll ist und das entsprechende Unterprogramm ausgeführt werden soll. Zum Beispiel verhindert die Variable »L« in Zeile 8025, daß Daten gespeichert werden, wenn die Datei noch gar nicht in den Speicher des Computers geladen wurde. Das würde nämlich bewirken, daß (in diesem Fall die Datei »ADRESS«) überschrieben würde ohne es zu wollen; auf Diskette vorhandene Daten wären verloren. Also eine reine Sicherheitsmaßnahme.
Sicherheit ist Trumpf
Die Variable »SS« verhindert, daß das Programm beendet wird, ohne neu eingegebene Daten vorher abzuspeichern.
Zuletzt möchte ich noch auf einen Programmteil hinweisen, der ab Zeile 10000 steht. Dieses Unterprogramm wird immer dann angesprungen, wenn eine Datei eröffnet wird. Es können nämlich auch dann Fehler auftreten, wenn das Programm sonst einwandfrei funktioniert. Es kann zum Beispiel sein, daß sie eine schreibgeschützte Diskette benutzen wollen, um Daten abzuspeichern. Das funktioniert natürlich nicht. Damit das Programm dann nicht abstürzt, wird jedesmal nach einem Öffnen eines Floppy-Kanals diese Routine angesprungen. Sie können dann im Fehlerfall das Problem beseitigen, ohne das Programm neu starten zu müssen und damit eventuell alle eingegebenen Daten zu verlieren. Der Fehler »62« in Zeile 10062 weist übrigens darauf hin, daß ein »FILE NOT FOUND ERROR« gemeldet wurde. In diesem Fall kann eine neue Datei angelegt werden (ab 11000). Man kann natürlich auch andere Fehler direkt abfragen. Schauen Sie nach im Floppy-Handbuch von Commodore. Dort sind alle Fehlermeldungen erklärt.
Ich glaube, daß Sie viele Möglichkeiten finden werden, eine sequentielle Datei sinnvoll einzusetzen. Setzen Sie sich hin und fangen Sie an zu programmieren und zu experimentieren. Erweitern Sie Ihr Wissen durch eigene Erfahrungen. Tippen Sie nicht nur ab, seien Sie kreativ!
(Christian Schlüter/gk)100 rem ****************************** 110 rem * adressendatei 64'er/6 * 120 rem ****************************** 130 : 131 rem ***** steuerzeichen ***** 132 rem * * 133 rem * <clr> = clr/home * 134 rem * <crr> = cursor rechts * 135 rem * <crl> = cursor links * 136 rem * * 137 rem ************************* 138 : 140 di=200 150 dim nv$(di),nn$(di),sr$(di) 160 dim pl$(di),ot$(di),te$(di) 170 poke 53281,0 180 close 15:open 15,8,15 1000 rem ---------------------------- 1010 rem - menue - 1020 rem ---------------------------- 1030 : 1040 print "{clr}" 1050 print :print 1060 print " adressendatei" 1070 print :print 1080 print " x = programmende" 1090 print 1100 print " 1 = anzeigen gesamte datei" 1110 print 1120 print " 2 = suchen" 1130 print 1140 print " 3 = loeschen" 1150 print 1160 print " 4 = aendern" 1170 print 1180 print " 5 = neue adressen eingeben" 1190 print 1200 print " 6 = speichern" 1210 print :print :print :print 1220 print "waehlen sie "; 1230 get r$:if r$="" then 1230 1240 if r$="x" then 1500 1250 if r$="1" then gosub 2000:rem anz. 1260 if r$="2" then gosub 3000:rem such 1270 if r$="3" then gosub 4000:rem del 1280 if r$="4" then gosub 5000:rem aen 1290 if r$="5" then gosub 6000:rem neu 1300 if r$="6" then gosub 8000:rem spei 1310 goto 1000 1320 : 1500 rem ---------------------------- 1510 rem - programm ende - 1520 rem ---------------------------- 1530 rem ss=2 wenn nicht gespeichert 1540 if ss=1 then gosub 8000 1550 close 15 1560 end 1570 : 1580 : 2000 rem ------------------------------ 2010 rem - anzeigen gesamte datei 2020 rem ------------------------------ 2030 : 2040 if l=0 then gosub 9000:rem laden 2050 for i=1 to nd 2060 :print "{clr} anzeige der datei" 2065 :print 2070 :print " nummer ";i:print 2075 :print 2080 :print " name : "nv$(i)" "nn$(i) 2100 :print " strasse : "sr$(i) 2110 :print " plz/ort : "pl$(i)" "ot$(i) 2130 :print " telefon : "te$(i) 2150 :print :print :print 2160 :print " w = weiter x = ende" 2170 :get r$:if r$="" then 2170 2180 :if r$="x" then 2200 2190 next i 2200 return 2210 : 6000 rem ------------------------------ 6010 rem - eingabe neue daten - 6020 rem ------------------------------ 6030 : 6040 if l=0 then gosub 9000:rem laden 6050 print "{clr}" 6060 print " eingabe neue daten" 6070 print :print 6075 nd=nd+1 6076 print " nummer ";nd 6078 print :print 6080 input "nachname {rght}{rght}{rght}.{left}{left}{left}";nn$(nd) 6090 input "vorname {rght}{rght}{rght}.{left}{left}{left}";nv$(nd) 6100 input "strasse {rght}{rght}{rght}.{left}{left}{left}";sr$(nd) 6110 input "postlz. {rght}{rght}{rght}.{left}{left}{left}";pl$(nd) 6120 input "ort {rght}{rght}{rght}.{left}{left}{left}";ot$(nd) 6130 input "telefon {rght}{rght}{rght}.{left}{left}{left}";te$(nd) 6140 print :print 6150 print "w = weitere adresse x = ende" 6160 get r$:if r$="" then 6160 6170 if r$="w" then 6050 6175 ss=1:rem daten neu eingegeben 6180 return 6190 : 8000 rem ---------------------------- 8010 rem - speichern datei auf disk - 8020 rem ---------------------------- 8025 rem l=0 wenn noch nicht geladen 8030 if l=0 then 8170 8040 close 1:open 1,8,2,"@:adresse,s,w" 8050 gosub 10000:rem diskettenfehler? 8060 if a1<>0 then 8040 8070 print# 1,nd 8080 for i=1 to nd 8083 :print "{clr} speichern der daten" 8085 :print i" von "nd 8090 :print# 1,nv$(i) 8100 :print# 1,nn$(i) 8110 :print# 1,sr$(i) 8120 :print# 1,pl$(i) 8130 :print# 1,ot$(i) 8140 :print# 1,te$(i) 8150 next i 8160 close 1 8165 ss=2:rem letzten stand gespeichert 8170 return 8180 : 9000 rem ---------------------------- 9010 rem - laden der datei von disk - 9020 rem ---------------------------- 9030 i=0 9040 close 1:open 1,8,2,"adresse,s,r" 9045 gosub 10000:rem diskettenfehler? 9046 if a1<>0 then 9030 9047 input# 1,nd$:nd=val(nd$) 9048 i=i+1 9049 print "{clr}"i" von "nd 9050 input# 1,nv$(i) 9060 input# 1,nn$(i) 9070 input# 1,sr$(i) 9080 input# 1,pl$(i) 9090 input# 1,ot$(i) 9100 input# 1,te$(i) 9110 if (st and 64)<>64 then 9048 9120 close 1 9130 l=1:rem datei ist geladen 9140 return 9150 : 10000 rem ---------------------------- 10010 rem - diskettenfehler - 10020 rem ---------------------------- 10030 print "{clr}" 10050 input# 15,a1,a2$,a3,a4 10060 if a1=0 then 10170 10062 if a1=62 then gosub 11000:goto 10170 10065 print 10070 print a1,a2$;a3;a4 10080 print :print 10090 print " diskettenfehler" 10100 print :print 10110 print " beheben sie den fehler" 10120 print " und druecken sie" 10130 print 10140 print " >> f <<" 10150 get r$:if r$="" then 10150 10160 print "{clr}" 10170 return 10180 : 11000 rem --------------------------- 11010 rem - neue datei anlegen 11020 rem --------------------------- 11030 : 11040 print "{clr}" 11050 print " die datei existiert noch nicht" 11060 print :print 11070 print "n = neue datei x = ende" 11080 get r$:if r$="" then 11080 11090 if r$="x" then run 11100 if r$<>"n" then 11080 11140 close 1:open 1,8,2,"adresse,s,w" 11150 for i=1 to 7 11160 :print# 1,"." 11170 next i 11180 close 1 11200 return