Die Community zu .NET und Classic VB.
Menü

Binäre Dateien

 von 

Übersicht 

Folgend, der nun letzte Teil des Tutorials über Dateimanipulationen. Diesmal geht es um die binären Dateizugriffe. Es ist hierbei zum besseren Verständnis ratsam, vorab den Artikel über die Random-Dateien gelesen zu haben.

Mit freundlichen Grüßen
i.A. Götz Reinecke,

Dieses Tutorial wurde am 13.10.2007 durch Philipp Burch geringfügig überarbeitet und ergänzt.

Binärdateien öffnen  

Eine Binärdatei ist eigentlich eine spezielle Form einer typisierten Datei. Die Datensatzlänge kann vom Datensatz zu Datensatz unterschiedlich sein, was alleine vom verwendeten Datentyp der Variablen abhängt. Es ist hierbei also möglich, daß der erste Datensatz in eine Variable vom Typ Long gespeichert wird, der nächste in eine Variable vom Typ Byte usw. Es werden jeweils so viele Bytes gelesen bzw. geschrieben wie die Variable groß ist. Das sollte stets im präsent sein, denn es kann schnell passieren, daß man an einer falschen Stelle der Datei versucht mit einem nicht passenden Variabelentyp Daten zu lesen bzw. zu speichern. Es kommt dabei zu keiner Fehlermeldung, man erhält jedoch falsche Werte oder im schlimmsten Falle wird die Datei teilweise unbrauchbar.

Bei den Binärdateien gibt es wie bei den typisierten Dateien kein Trennzeichen zwischen den Datensätzen, die Daten werden hintereinander in die Datei geschrieben.
"Binärdatei" ist eigentlich eine völlig falsche Bezeichnung. Binär hieße eigentlich die kleinste Speichermöglichkeit von Daten [Bit], also nur 0 oder 1 zu verwenden. Man speichert jedoch die Datei in Binärdateien nicht als einzelne Nullen oder Einsen sondern vielmehr als ganze Bytes [ein Byte besteht aus acht Bits]. Also sollten die Dateien eigentlich Bytedateien heißen, wir bleiben jedoch bei der offiziellen Bezeichnung. Um eine Binärdatei zu öffnen muss, man nicht eine höhere Schule besucht haben, es reicht lediglich dieses Tutorial aufmerksam zu lesen und den folgenden Befehl zu benutzen:

Open Dateiname For Binary As Dateinummer

Die Parameter Dateiname und Dateinummer sollten bereits bekannt sein, so daß hier keine entsprechende Beschreibung stattfindet. Wichtig ist jedoch noch, daß im Binary-Modus der Len- Abschnitt [falls mitangegeben] nicht beachtet.

Beispiel:

Dim FN As Integer
FN = FreeFile
Open "C:\test.txt" For Binary As FN

Listing 1

Was hat es hierbei mit dem Satzzeiger an sich?

Mit dem Seek-Befehl kann man wie bei den typisierten Dateien den Satzzeiger in der Datei bewegen bzw. die Position abfragen. Es besteht jedoch ein gravierender Unterschied den man nicht vergessen sollte:
Wird die Position bei den typisierten Dateien in Datensätzenbestimmt ist es bei den binären Dateien völlig anderes. Hier wird die Position in Bytes bestimmt! Das heißt also, daß der Datensatzzeiger bei jedem Zugriff auf die Datei, sei es schreibend oder lesend, immer um die Anzahl von Bytes verschoben wird wie die Variable groß ist. Wenn wir z.B. einen Wert aus der Datei lesen dessen Größe 1 Byte ist (eine Bytevariable) wird der Satzzeiger um eins verschoben, lesen wir jetzt einen Longwert (eine Longvariable) wird der Satzzeiger um vier verschoben, da die Longvariable vier Bytes groß ist.

Später werde ich es an einem Beispiel versuchen zur verdeutlichen.

Daten aus einer Binärdatei lesen  

Hierzu nutzt man wie bei den typisierten Dateien den Get-Befehl. Die Syntax ist identisch, so daß es keine gesonderten Beschreibung nötig ist. Man sollte jedoch immer an den Byte-Satzzeiger denken. Hier möchte ich nun das angesprochene Beispiel vorstellen, an dem man das Verhalten des Satzzeigers leicht erkennen kann.

Dim Data1 As Byte
Dim Data2 As Long
Dim Data3() As Byte
Dim FN As Integer

FN = FreeFile
Open "C:\Test.txt" For Random As FN Len = Len(Data2)
MsgBox "Satzzeiger steht an der Position: " & Seek(FN)

Get FN, , Data2
MsgBox "Satzzeiger steht an der Position: " & Seek(FN)

Get FN, , Data2
MsgBox "Satzzeiger steht an der Position: " & Seek(FN)

Close FN

ReDim Data3(9)    'Sehr wichtig, sonst liest Get nichts aus!
Open "C:\Test.txt" For Binary As FN
MsgBox "Satzzeiger steht an der Position: " & Seek(FN)

Get FN, , Data2
MsgBox "Satzzeiger steht an der Position: " & Seek(FN)

Get FN, , Data2
MsgBox "Satzzeiger steht an der Position: " & Seek(FN)

Get FN, , Data1
MsgBox "Satzzeiger steht an der Position: " & Seek(FN)

Get FN, , Data1
MsgBox "Satzzeiger steht an der Position: " & Seek(FN)

Get FN, , Data3
MsgBox "Satzzeiger steht an der Position: " & Seek(FN)
Close FN

Listing 2

Zuerst wird eine Datei im Random-Modus [also als typisierte Datei] geöffnet und die Datensatzlänge auf die Länge von Data2 eingestellt. Danach wird die Position des Satzzeigers in eine MsgBox ausgegeben, diese sollte direkt nach dem Öffnen der Datei auf eins stehen. Jetzt wird ein Datensatz aus der Datei gelesen und der Datensatzzeiger automatisch auf den nächsten Datensatz gebracht. Dieser wird wieder in der MsgBox angezeigt. Obwohl wir vier Bytes aus der Datei gelesen haben, zeigt der Satzzeiger auf den zweiten Datensatz. Das ist bei typisierten Dateien auch richtig so.

Beim nächstem Lesen aus der Datei wird der Datensatzzeiger wieder um eins erhöht. Wir schließen jetzt die Datei und öffnen sie erneut, diesmal jedoch im binären Modus. Die MsgBox zeigt, dass der Datensatzzeiger nach dem Öffnen der Datei, wie bei den typisierten Dateien, auf eins steht. Jetzt lesen wir einen Long-Wert aus der Datei. Der Datensatzzeiger steht diesmal nicht auf zwei sondern auf fünf. Das ist völlig korrekt, ist doch eine Longvariable vier Bytes groß und 1 + 4 = 5.

Jetzt wird noch mal ein Longwert gelesen, der Satzzeiger steht dann also auf 9. Als nächstes wird ein Bytewert gelesen und der Satzzeiger um ein Byte erhöht, was 10 ergibt. Wie es in dem Code weiter geht sollte eigentlich schon jedem bekannt sein.

Am Ende wird nun noch ein ganzes Array auf einen Schlag gelesen. Hier ist zu beachten, dass das Array vor dem lesen auf die gewünschte Länge initialisiert wird, da Get sonst nicht weiss, wie viel gelesen werden muss.

Wie man bereits sehen kann, ist es nicht ohne weiteres möglich, Daten die nicht von konstanter Länge sind mitten aus der Datei zu lesen, es sei denn man merkt sich die Position an der die Daten liegen und liest diese mit der Datensatznummer aus. Sollte die Position der Daten in der Datei bekannt sein ist es empfehlenswert diese mit in den Get-Befehl einzugeben.

Noch eine Anmerkung am Rande. Sollte man unter VB 3 mit Byte-Werten gearbeitet haben (Nachbildung eines Byte as String * 1) muss man diese Definition ab VB 4 in den neuen Datentyp Byte umwandeln da mittlerweile die Deklaration String * 1 einem zwei Byte langen Wert entspricht.

In eine Binärdatei schreiben  

Wie wahrscheinlich schon vermutet, geschieht dies mit dem gleichen Befehl, wie bei den typisierten Dateien. Außer der Besonderheit des Satzzeigers besteht hier überhaupt kein Unterschied. Aus diesem Grund spare ich mir eine genauere Beschreibung und komme direkt zu einem Beispiel. Bei diesem Beispiel handelt es sich um eine leicht abgeänderte Version des Programms, indem die letzte Fensterposition gespeichert und wieder gelesen werden kann, mit dem Unterschied, daß hier auch die WindowState-Eigenschaft mitgespeichert und berücksichtigt wird.

Option Explicit

Private Type WindowPos
  x As Integer
  y As Integer
  w As Integer
  h As Integer
End Type
    
Public Sub Form_Load()
  If FileExist("WindowPrefs.dat") Then
    
    Dim FN As Integer
    Dim Data As Long
    
    FN = FreeFile
    Open "WindowPrefs.dat" For Binary As FN
    Get FN, , Data
    If Data > 3 Then Goto DatenFalsch
    
    Form1.WindowState = Data
    If Form1.WindowState = 0 Then
      Dim wp As WindowPos
      
      Get FN, , wp
      
      Me.Left = wp.x
      Me.Top = wp.y
      Me.Width = wp.w
      Me.Height = wp.h
    End If
    
DatenFalsch:
    Close FN
  End If
End Sub

'...
' hier geht das Programm weiter
'...

Public Sub Form_Unload(Cancel As Integer)
  Dim FN As Integer
  Dim Data As Long
  
  FN = FreeFile
  Open "WindowPrefs.dat" For Binary As FN
  Data = Form1.WindowState
  Put FN, , Data
  
  If Data = 0 Then
    Dim wp As WindowPos
    
    wp.x = Me.Left
    wp.y = Me.Top
    wp.w = Me.Width
    wp.h = Me.Height
    
    Put FN, , wp
  End If
  
  Close FN
End Sub

' und noch eine Funktion mit der man das Vorhandensein
' eine Datei überprüft
Public Function FileExist(Dateiname As String) As Boolean
  On Error Goto Fehler
  FileExist = Dir$(Dateiname) <> ""
  Exit Function
  
Fehler:
  FileExist = False
  Resume Next
End Function

Private Sub Command1_Click()
  Unload Me
End Sub

Listing 3

Wie man sieht, ist es mit Put und Get auch bei binären Dateien problemlos möglich, benutzerdefinierte Typen ohne Umwege zu schreiben und zu lesen.

Wichtigste Änderungen zur letzten Version:

  • Fensterdaten werden in Binärdatei gespeichert.
  • Zusätzlich wird der Fensterstatus mitgespeichert.
  • Wenn das Fenster geschlossen wird und es maximiert ist, werden die Fensterdaten nicht in die Datei gespeichert.
  • Beim Öffnen werden die Fensterdaten nicht eingestellt, wenn das Fenster maximiert angezeigt werden soll.

So jetzt sind wir am Ende des Tutorials angelangt, kennen uns mit den drei Datenarten aus, wissen wie man die lesen und schreiben kann und was man dabei beachten soll. Jetzt möchte ich noch eins loswerden: In den Modi Binary, Input und Random kann eine Datei mit einer anderen Dateinummer geöffnet werden, ohne sie zuvor schließen zu müssen. In den Modi Append und Output muss eine Datei immer erst geschlossen werden, bevor sie mit einer anderen Dateinummer geöffnet werden kann.

Nun steht das Tutorial zur Diskussion. Fragen, Anregungen, Korrekturen können ins Forum gepostet werden die dann von allen besprochen werden können oder ihr könnt mir auch mailen.

Komplettes Tutorial als PDF-Datei [479000 Bytes]

Ihre Meinung  

Falls Sie Fragen zu diesem Tutorial haben oder Ihre Erfahrung mit anderen Nutzern austauschen möchten, dann teilen Sie uns diese bitte in einem der unten vorhandenen Themen oder über einen neuen Beitrag mit. Hierzu können sie einfach einen Beitrag in einem zum Thema passenden Forum anlegen, welcher automatisch mit dieser Seite verknüpft wird.