
Übersicht
Einleitung
1. Grundlagen
2. Variablen
3. Schleifen
4. Entscheidungen
5. Struktur
6. Eingabe
7. Gfx-Grundlagen
8. Bilder anzeigen
9. Kollision
10. Sound & Musik
11. Dateien
12. Multiplayer

Spiele
Grafik
Mathe
Netzwerk
String
Verschiedenes
|
Mit Dateien arbeiten
© Robert Gerlach 2001-2002
www.robsite.de
Eigentlich ist der Titel Mit Dateien arbeiten etwas ungenau, denn bis jetzt haben
wir schon ziemlich oft mit Dateien gearbeitet, nämlich indem wir Bilder und Sounddateien
geladen haben. In diesem Kapitel geht es allerdings um die Grundlagen, um Manipulation von einzelnen
Zeichen in Dateien. Am Anfang gehts erstmal nur um Textdateien, da sie am einfachsten zu
bearbeiten sind. Nun denn, öffnen wir erstmal eine Datei.
Als Dateiendung kann man alles nehmen was das
Alphabet hergibt, nur sollte man schon benutzte Dateiendungen nicht nehmen... außer man will genau
so eine Datei erstellen (z.B. eine .bmp Datei), dann müsste man allerdings wieder den Aufbau
einer solchen kennen...
OpenFile kann nur Dateien öffnen die bereits existieren. Die Datei wird also nicht extra
erstellt wenn sie nicht existiert.
Gut, öffnen wir also erstmal eine ASCII-.txt Datei. Sie sollte möglichst schon existieren, sonst gibts
einen Fehler...:
stream = OpenFile("bopp.txt")
|
Die Datei-Variable heisst stream ("Datenfluß") weil wir soeben einen Datenstream zu einer Datei
geöffnet haben. Immer wenn man eine Verbindung zu einer Datei auf der Festplatte, einem Server u.s.w. aufbaut ist
das so als wenn man... einen Fluß (Stream) zwischen dem eigenen Programm und dem geöffneten...
Gerät/Gebiet auf der Festplatte/... eingerichtet hat auf dem dann die Daten hin und her geschickt werden
können.
Gut. Nun haben wir Lese- und Schreibzugriff auf die Datei bopp.text. Wollen wir zufällig
nur Lesezugriff oder nur Schreibzugriff haben, können wir selbiges erreichen
indem wir die Datei anders öffnen. ReadFile kann amn auch nur auf schon bestehende
Dateien anwenden, nur WriteFile erstellt eine wenn sie nicht existiert.
; Datei nur zum schreiben öffnen:
stream = WriteFile("bopp.txt")
; Datei nur zum lesen öffnen:
stream = ReadFile("bopp.txt")
|
Im Moment ist aber erstmal OpenFile das beste, wir brauchen uns immerhin keine Gedanken
darüber zu machen ob wir nun lesen oder schreiben können. Schreiben wir also etwas.
Es gibt viele Möglichkeiten Daten in Dateien abzulegen. Man kann einzelne Bytes speichern, aber auch
Integerzahlen (die aus 4 Bytes bestehen), Shortzahlen, Strings, Floatzahlen u.s.w. Man sollte
für jede Aufgabe möglichst immer das kleinstmögliche nehmen. Speichert man z.B. nur Buchstaben
nimmt man einzelne Bytes. Warum? Weil ein Byte die Werte 0-255 annehmen kann und die ASCII-Werte
eines Buchstaben ebenfalls von 0-255 gehen. Ideal also.
Um nun ein Byte beliebigen Wertes in der Datei bopp.txt zu speichern, schreiben wir
folgendes:
Öffnen wir jetzt die eben erstellte Datei mit einem Texteditor (Notepad), müsste ein großes R drinstehen, denn der ASCII-Wert
von R ist 82. Nun kann man sich aber nicht ohne größeren Zeitaufwand alle
255 ASCII-Zeichen merken, weshalb es den Asc() Befehl gibt. In den Klammern steht das
Zeichen und rauskommt sein ASCII-Code. Ein R kann man also auch so in eine Datei schreiben:
WriteByte stream, Asc("R")
|
Schon gleich viel besser. Wer zufällig auch mal alle Zeichen die es so gibt in einer Datei haben will, führe
folgenden Code aus:
stream = OpenFile("alle_ascii_zeichen.txt")
For ascii = 1
To 255
WriteByte stream, ascii
Next
|
Das aber nur nebenbei. Weiter mit anderen Datenarten. Die Befehle dazu sind sich alle sehr
ähnlich, nur die Byte-Werte der Typen sind unterschiedlich. Hier eine kleine Tabelle dazu:
Befehl
|
Name
|
Bytes
|
Typ
|
Von
|
Bis
|
WriteByte stream, wert
WriteShort stream, wert
WriteInt stream, wert
WriteFloat stream, wert#
WriteLine stream, wert$
WriteString stream, wert$
|
Byte
Short
Integer
Float
Line
String
|
1
2
4
4
0-x
4-x
|
Ganzzahl
Ganzzahl
Ganzzahl
Kommazahl
Text
Text
|
0
-32768
-2147483648
-2 Mrd.
0
4
|
255
32767
2147483647
2 Mrd.
x
x
|
WriteByte haben wir eben kennengelernt, die nächst größere Einheit ist eine Short-Zahl, sie
ist sozusagen der kleine Ableger einer Integerzahl denn sie hat nur halb soviel Bytes wie sie und
kann somit nur begrenzt große Zahlen darstellen.
Integerzahlen mit 4 Bytes werden wohl am häufigsten
verwendet, auch wenn man oft nie über die 32768-Zahlengrenze der Shortzahlen kommt. Es ist zwar heute
nicht mehr so wichtig ob man 2 statt 4 Bytes irgendwo auf der riesigen Festplatte gespeichert hat,
nur wenn man sie wieder in den, viel kleineren, Arbeitsspeicher lädt können um die
Hälfte kleinere Zahlen doch schon eine Menge ausmachen. Wenn es sehr viele sind...
Will man dagegen exakte Kommazahlen abspeichern, tut man dies mit WriteFloat, Floatzahlen
sind auch 4 Bytes groß.
Das wars mit den Zahlen, was folgt sind die Strings, also Text. Man kann Strings in 2 Arten
speichern, Zeilen- und Zeichenweise. Um iene Zeile voll mit ASCII-Zeichen zu speichern, nimmt man
WriteLine datei, Text$, man kann dann beliebig viele Zeichen im Text-String abspeichern.
Damit man nachher beim auslesen erkennt das am Ende das Zeilenende ist fügt Blitz noch ein
Returnzeichen (0dh <-- Hexadezimalzahl, später mehr dazu.) ein. Will man also längere Texte
oder Zeichenketten in eine Datei schreiben, nehme man WriteLine. WriteString macht
so ziemlich das gleiche, nur dass bei ihm noch vor dem Text eine Integerzahl steht die die Länge
der Nachfolgenden Zeichenkette angibt. Somit ist ein WriteString-String minimal 4 Bytes groß, ein
mit WriteLine abgespeicherter minimal 0 (praktisch wenn man nur eine Leerzeile ohne Speicherverbrauch
haben will).
Ein kleines Beispielprogramm was alles mögliche in einer Datei speichert:
; Datei zum schreiben öffen, Stream
anlegen.
datei = WriteFile("bopp.txt")
; Ein Byte speichern
WriteByte datei, 78
; Ein Byte mit Hilfe von Asc() speichern.
WriteByte datei, Asc("D")
; Eine Shortzahl speichern:
WriteShort datei, 23
; Eine Integerzahl speichern:
WriteInt datei, 5
; Eine Floatzahl speichern:
WriteFloat datei, 1949.235
; Eine Zeile Speichern:
WriteLine datei, "Preisfrage:
Würde Toblerone schmelzen"
; Einen String-datensatz speichern:
WriteString datei, "wenn
man sie in die Super-ILLU einpacken würde? Wer weiß..."
CloseFile datei
|
Der letzte Befehl (CloseFile)ist wichtig, er schließt die Datei nämlich wieder, trennt also den Stream.
Das sollte man möglichst nie vergessen...
Öffnet man jetzt die durch das Programm erstellte Datei wird man ein ziemlich chaotisches Bild vorfinden.
Notepad kann anscheinend nur ASCII-Text, also einzelne Bytes, lesen und anzeigen, bei
Short-, Integer- und Floatzahlen macht es schlapp. Nur mit den richtigen Methoden/Befehlen
können wir z.B. eine mit WriteShort in eine Datei geschriebene Zahl wieder auslesen und
anzeigen.
Die Befehle zum auslesen von Werten unterscheiden sich nicht sehr von denen zum schreiben, nur dass
sie... umgekehrt funktionieren...:
; Um ein Byte auszulesen:
wert = ReadByte(stream)
; Um eine Shortzahl auszulesen:
wert = ReadShort(stream)
; Um eine Integerzahl auszulesen:
wert = ReadInt(stream)
; Um eine Floatzahl auszulesen:
wert# = ReadShort(stream)
; Um eine Zeile auszulesen:
wert$ = ReadLine$(stream)
; Um einen String auszulesen:
wert$ = ReadString$(stream)
|
Man muss einen mit einem bestimmten Befehl abgespeicherten Wert immer genau mit seinem Lese-Gegenstück
auslesen. Also ein Byte mit ReadByte und nicht mit ReadFloat u.s.w.
Nun können wir in dateien schreiben und das ganze auch noch auslesen. Bevor es weitergeht mit Methoden wie
man das ganze am besten macht, noch ein paar nützliche Befehle rund um Dateien.
Weiß man nicht ob eine Datei überhaupt existiert, kann man das folgendermaßen prüfen:
rueckgabe = FileType("dateiname.dat")
|
rueckgabe hat danach folgende Werte:
0 - Die Datei existiert nicht.
1 - Die Datei existiert.
2 - Es ist keine Datei sondern ein Verzeichnis ^_^
So kann amn mit FileType also auch noch prüfen ob ein bestimmtes Verzeichnis existiert.
Sehr praktisch.
Will man nun z.B. die Größe einer Datei haben, nehme man FileSize:
groeße = FileSize("dateiname.dat")
|
Es wird dann die Größe in Bytes zurückgegeben. Nochmal zur Erinnerung:
8 Bit = 1 Byte
1024 Byte = 1 KiloByte
1024 KiloByte = 1 MegaByte
1024 MegaByte = 1 GigaByte
u.s.w.
So kann man sich auch einfach eine kleine Function schreiben die die Größe in KB zurückgibt:
Function DateiKB#(datei$)
groeße# = FileSize(datei$) / 1024
Return groeße#
End Function
|
Das aber nur nebenbei...
Nun noch kurz zwei Standardbefehle die man immer mal braucht:
; Um eine Datei zu kopieren:
CopyFile quellpfad$, zielpfad$
; Um eine Datei zu löschen:
DeleteFile dateipfad$
|
Und um sich in Verzeichnissen/Ordnern zu bewegen oder selbige zu löschen gibt es noch folgende Befehle:
; Um ein neues Verzeichnis zu
erstellen:
CreateDir Verzeichnispfad$
; Um herauszufinden in welchem Verzeichnis man sich
gerade befindet:
Verzeichnispfad$ = CurrentDir()
; Falls man in ein anderes Verzeichnis wechseln will:
ChangeDir Neuer_Verzeichnispfad$
; Um ein Verzeichnis zu löschen nehme man:
DeleteDir Verzeichnispfad$
|
Man kann aber auch noch mehr mit Verzeichnissen machen, z.B. alle Dateien in ihnen auswählen.
Dazu muss man erstmal das Verzeichnis seiner Wahl öffnen:
Verzeichnisvariable = ReadDir(Verzeichnispfad$)
|
Nun kann amn in diesem Verzeichnis Dateien auswählen:
Dateipfad$ = NextFile(Verzeichnisvariable)
|
Mit NextFile geht man also immer eine Datei in dem Verzeichnis weiter. Damit kann man sich
z.B. eine DIR Funktion wie in MS-DOS schreiben, welche alle Dateien und Unterverzeichnisse
in einem Ordner auflistet. Hier eine kleine DIR-Funktion:
Function dir(verzeichnis$)
ordner = ReadDir(verzeichnis$) ;
Verzeichnis öffnen.
; Schleife in der das ganze geprüft und ausgegeben
wird.
Repeat
datei$ = NextFile(ordner) ;
Neue Datei auswählen.
; Überprüfen ob sie eine Datei oder ein Verzeichnis
ist und dementsprechend... was anderes hinschreiben.
If FileType(verzeichnis$ + datei$) = 2
Then
Print datei$ + " &DIR>"
Else
Print datei$
EndIf
Until datei$ = ""
CloseDir ordner ; Verzeichnis
schließen.
End Function
|
Einfach dir("C:\") eingeben und sehen was so alles im C:\ Verzeichnis rumlungert.
CloseDir schließt ein Verzeichnis übrigens wieder...
Und nun zu ein paar kleinen Beispielen zu praktischen Anwendung von dem ganzen, komplett mit ein paar
nützlichen Functions.
Will man z.B. ein Array (DIM-Feld) in einer Datei schreiben und wieder auslesen, kann man das
z.B. so machen:
; Ein Feld erstellen.
Dim feld(10, 10)
; Zufallswerte erzeugen
For x = 1 To
10
For y = 1 To
10
feld(x, y) = Rnd(1,
10)
Next
Next
; Eine Datei zum schreiben öffnen.
datei = WriteFile("feld-test.txt")
; Die Werte des Feldes in der Datei speichern. Mit
Writebyte da die Werte nicht über 255 gehen.
For x = 1 To
10
For y = 1 To
10
WriteByte datei, feld(x, y)
Next
Next
; Die Datei schließen.
CloseFile datei
|
Öffnet man nun diese Datei sieht man wahrscheinlich viele kleine Kästchen, wir haben ja auch keine
Buchstaben gespeichert. Um nun das ganze wieder in ein neues Feld einzulesen können wir folgendes machen:
; Neues Feld erstellen:
Dim neuesfeld(10,
10)
; Die eben erstellte Datei wieder öffnen:
datei = ReadFile("feld-test.txt")
; Die Werte in das Feld einlesen und ausgeben:
For x = 1 To
10
For y = 1 To
10
neuesfeld(x, y) = ReadByte(datei)
Print neuesfeld(x, y)
Next
Next
Die Datei wieder schließen:
CloseFile datei
|
Das war einfach. Was aber wenn man z.B. eine Datei mit diesem Aufbau hat:
23,5,19,49
94,9,145,32
12,456,73,9
u.s.w.
|
Also wenn in einer Zeile jeweils 4 unterschiedlich lange Zahlen durch Kommas getrennt gespeichert sind?
Dann sollte man die Datei Zeile für Zeile (ReadLine) auslesen und die Zahlen aus
dem String extrahieren. Dies ist etwas komplizierter, normalerweise. Man kann aber auch meine
bewährte ZahlAusString-Function nehmen ^_^. Um das Beispiel auszuprobieren solltest du
am besten eine Datei zeilenzahlen.txt erstellen die in jeder Zeile 4 durch Kommas getrennte
Zahlen hat. Die Zeilenanzahl ist egal.
; Eine Datei öffnen.
datei = ReadFile("zeilenzahlen.txt")
; Schleife solange wiederholen bis das Ende (Eof -->
End of File) der Datei erreicht ist.
While Not Eof(datei)
; Eine Zeile auslesen:
zeile$ = ReadLine(datei)
; Jeweils die erste bis vierte Zahl extrahieren und
in eine eigene Variable speichern.
zahl1 = zahlausstring(zeile$, 1)
zahl2 = zahlausstring(zeile$, 2)
zahl3 = zahlausstring(zeile$, 3)
zahl4 = zahlausstring(zeile$, 4)
; Die Zahlen ausgeben.
Print zahl1 + " "
+ zahl2 + " " + zahl3 + "
" + zahl4
Wend
; Die Function die die ganze Arbeit macht...
;------------------------------------------------------
; zahlstring$ ist der String in dem die Zahlen stehen, stelle ist die Stelle
der Zahl. Wenn stelle = 3 ist wird also die dritte Zahl zurückgegeben.
; Muss man nicht verstehen, nur benutzen können ^_^.
Function zahlausstring(zahlstring$, stelle)
anzahl = 1
letzteskomma = 1
For i = 1 To
Len(zahlstring$)
If Mid(zahlstring$, i, 1)
= "," Or i = Len(zahlstring$)
Then
If anzahl = stelle Then
zahl = Mid(zahlstring$, letzteskomma, i)
letzteskomma = i + 1
anzahl = anzahl + 1
EndIf
Next
Return zahl
End Function
|
Nun können wir schon so ziemlich alles mit Dateien machen was man so brauchen könnte.
Ein paar Sachen fehlen noch, diese sind aber nicht unbedingt notwendig... Außerdem ist
diese Kapitel schon jetzt viel zu groß ^_^.
Wer die restlochen 2 Befehle haben will lese die Command Reference oder gehe auf www.blitzbase.de ^_^.
Zusammenfassung
; Eine bestehende Date zum lesen
und schreiben öffnen:
stream = OpenFile(dateipfad$)
; Eine bestehende Datei nur zum lesen öffnen:
stream = ReadFile(dateipfad$)
; Um eine Datei nur zum schreiben zu öffnen oder sie gleich dazu zu erstellen:
stream = WriteFile(dateipfad$)
; Die Befehle um verschiedene Datentypen in eine geöffnete
Datei zu schreiben:
WriteByte stream, wert
WriteInt stream, wert
WriteFloat stream, wert#
WriteLine stream, wert$
WriteString stream, wert$
; Und die Befehle um verschiedene Datentypen aus einer
geöffneten Datei zu lesen:
wert = ReadByte(stream)
wert = ReadInt(stream)
wert# = ReadFloat(stream)
wert$ = ReadLine(stream)
wert$ = ReadString(stream)
; Um herauszubekommen ob eine Datei existiert und
wenn ja ob es überhaupt eine Datei oder ein Verzeichnis ist ^_^:
rueckgabe = FileType(dateipfad$)
; rueckgabe hat dann folgende Werte:
; 0 = Datei/Ordner existiert nicht.
; 1 = Datei existiert.
; 2 = Es ist keine Datei sondern ein Ordner.
; Um die Größe einer Datei in Bytes zu bekommen:
groesse = = FileSize(dateipfad$)
; Um eine Datei zu kopieren:
CopyFile quellpfad$, zielpfad$
; Um eine Datei zu löschen:
DeleteFile dateipfad$
; Um ein neues Verzeichnis zu erstellen:
CreateDir Verzeichnispfad$
; Um herauszufinden in welchem Verzeichnis man sich
gerade befindet:
Verzeichnispfad$ = CurrentDir()
; Falls man in ein anderes Verzeichnis wechseln will:
ChangeDir Neuer_Verzeichnispfad$
; Um ein Verzeichnis zu löschen nehme man:
DeleteDir Verzeichnispfad$
; Um ein Verzeichnis zu öffnen um die Dateien und Unterverzeichnisse in
ihm auswählen zu können:
Verzeichnisvariable = ReadDir(Verzeichnispfad$)
; Um eine Datei aus einem geöffneten Verzeichnis auswählen
zu können (und um immer eine Datei weiter in dem Verzeichnis zu gehen):
Dateipfad$ = NextFile(Verzeichnisvariable)
|
Nun zum letzten und schwersten Teil des Blitz Basic Kurses, Multiplayer- und Netzwerkbefehle nebst
Methoden wie man sie am besten anwendet:
Druckversion
|
|