Rheinwerk Computing < openbook > Rheinwerk Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.

Inhaltsverzeichnis
1 Einführung
2 Grundlagen der Sprachsyntax
3 Klassendesign
4 Weitere Datentypen
5 Multithreading
6 Collections und LINQ
7 Eingabe und Ausgabe
8 Anwendungen: Struktur und Installation
9 Code erstellen und debuggen
10 Einige Basisklassen
11 Windows-Anwendungen erstellen
12 Die wichtigsten Steuerelemente
13 Tastatur- und Mausereignisse
14 MDI-Anwendungen
15 Grafiken mit GDI+
16 Drucken
17 Entwickeln von Steuerelementen
18 Programmiertechniken
19 WPF – Grundlagen
20 Layoutcontainer
21 WPF-Steuerelemente
22 Konzepte von WPF
23 Datenbankverbindung mit ADO.NET
24 Datenbankabfragen mit ADO.NET
25 DataAdapter
26 Offline mit DataSet
27 Datenbanken aktualisieren
28 Stark typisierte DataSets
A Anhang: Einige Übersichten
Stichwort

Buch bestellen
Ihre Meinung?

Spacer
<< zurück
Visual Basic 2008 von Andreas Kuehnel, Stephan Leibbrandt
Das umfassende Handbuch
Buch: Visual Basic 2008

Visual Basic 2008
3., aktualisierte und erweiterte Auflage, geb., mit DVD
1.323 S., 49,90 Euro
Rheinwerk Computing
ISBN 978-3-8362-1171-0
Pfeil 7 Eingabe und Ausgabe
Pfeil 7.1 Namensräume der Ein- bzw. Ausgabe
Pfeil 7.2 Ausnahmebehandlung
Pfeil 7.3 Dateien und Verzeichnisse
Pfeil 7.3.1 Dateizugriff mit File
Pfeil 7.3.2 Dateizugriff mit FileInfo
Pfeil 7.3.3 Die Klassen Directory und DirectoryInfo
Pfeil 7.3.4 Dateizugriffe in Aktion
Pfeil 7.3.5 Pfade mit Path
Pfeil 7.3.6 Laufwerksinformation mit DriveInfo
Pfeil 7.3.7 SpecialDirectories
Pfeil 7.4 Datenflüsse in Streams
Pfeil 7.4.1 Die abstrakte Klasse Stream
Pfeil 7.4.2 Stream-Klassen im Überblick
Pfeil 7.4.3 Dateizugriff mit FileStream
Pfeil 7.5 Texte mit TextReader und TextWriter
Pfeil 7.5.1 Texte mit StreamWriter schreiben
Pfeil 7.5.2 Texte mit StreamReader lesen
Pfeil 7.5.3 Zeichenketten mit StringWriter und StringReader
Pfeil 7.6 Binärdaten mit BinaryReader und BinaryWriter
Pfeil 7.6.1 Schreiben mit BinaryWriter
Pfeil 7.6.2 Lesen mit BinaryReader
Pfeil 7.6.3 Binäre Datenströme auswerten
Pfeil 7.6.4 Komplexe binäre Daten
Pfeil 7.7 Serialisierung
Pfeil 7.7.1 Serialisierungsverfahren
Pfeil 7.7.2 Testklassen
Pfeil 7.7.3 Serialisierung mit BinaryFormatter
Pfeil 7.7.4 Serialisierung mit SoapFormatter
Pfeil 7.7.5 Serialisierung mit XmlSerializer


Rheinwerk Computing - Zum Seitenanfang

7.6 Binärdaten mit BinaryReader und BinaryWriter Zur nächsten ÜberschriftZur vorigen Überschrift

Bis jetzt haben wir von den primitiven Datentypen Bytes sowie Zeichen und Zeichenketten mit Strömen verarbeitet. Nun kommen wir zu den anderen Primitiven.


Rheinwerk Computing - Zum Seitenanfang

7.6.1 Schreiben mit BinaryWriter Zur nächsten ÜberschriftZur vorigen Überschrift

Ein BinaryWriter-Objekt erzeugen Sie unter Angabe des zu schreibenden Stroms. Optional können Sie die Kodierung von zeichenbasierten Daten angeben:


Public Sub New(output As Stream) 
Public Sub New(output As Stream, encoding As Encoding)

Neben den Schreibroutinen gibt es nur Methoden zum Schließen, Pufferleeren und Setzen des Datenzeigers:


Public Overridable Sub Close() 
Public Overridable Sub Flush() 
Public Overridable Function Seek(offset As Integer, origin As SeekOrigin) 
                   As Long

Den Kern bilden die Methoden zum Schreiben verschiedener primitiver Datentypen. Die Typen werden binär übermittelt, zum Beispiel 4 Bytes für Integer und 8 Bytes für Double:


Public Overridable Sub Write(value As Datum)

Datum: Boolean, Byte, Char, Decimal, Double, Integer, Long, SByte, Short, 
       Single, String, UInt16, UInt32, UInt64

Von Bytes und Zeichen können ganze Arrays gleichzeitig geschrieben werden:


Public Overridable Sub Write(buffer As Byte()) 
Public Overridable Sub Write(chars As Char())


Rheinwerk Computing - Zum Seitenanfang

7.6.2 Lesen mit BinaryReader Zur nächsten ÜberschriftZur vorigen Überschrift

Ein BinaryReader-Objekt erzeugen Sie unter Angabe des zu lesenden Stroms. Optional können Sie die Kodierung von zeichenbasierten Daten angeben.


Public Sub New(input As Stream) 
Public Sub New(input As Stream, encoding As Encoding)

Neben den Leseroutinen gibt es nur Methoden zum Schließen und Lesen ohne Fortschritt des Datenzeigers:


Public Overridable Sub Close() 
Public Overridable Function PeekChar() As Integer

Den Kern bilden die Methoden zum Lesen verschiedener primitiver Datentypen. Es werden so viele Bytes gelesen, wie der Datentyp beansprucht, zum Beispiel 4 für Integer und 8 für Double. Die spezifischen Varianten lösen EndOfStreamException aus, wenn es nichts mehr zu lesen gibt.


Public Overridable Function Read() As Integer 
Public Overridable Function ReadDatum() As Datum

Datum: Boolean, Byte, Char, Decimal, Double, Integer, Long, SByte, Short, 
       Single, String, UInt16, UInt32, UInt64

Von Bytes und Zeichen können auch mehrere gleichzeitig eingelesen werden:


Public Overridable Function Read( _ 
  buffer As Byte(), index As Integer, count As Integer) As Integer 
Public Overridable Function ReadBytes(count As Integer) As Byte()

Public Overridable Function Read( _ 
  buffer As Char(),index As Integer, count As Integer) As Integer 
Public Overridable Function ReadChars(count As Integer) As Char()

Auf den zugrunde liegenden Strom greifen Sie mit der Eigenschaft BaseStream zu.


Public Overridable ReadOnly Property BaseStream As Stream


Rheinwerk Computing - Zum Seitenanfang

7.6.3 Binäre Datenströme auswerten Zur nächsten ÜberschriftZur vorigen Überschrift

Der Vorteil binärer Daten ist deren Effizienz bezüglich Speicherplatz und Geschwindigkeit. Ihr Nachteil ist der komplette Datenverlust, wenn auch nur ein Byte »falsch« interpretiert wird. Im folgenden Beispiel wird die Zahl 500 binär geschrieben und dann byteweise und als Text eingelesen.


'...\IO\Ströme\Binärdaten.vb

Option Strict On 
Imports System.IO 
Namespace EA 
  Module Binärdaten 
    Sub Test() 
      Dim path As String = IO.Path.GetTempFileName() 
      Dim fi As New FileInfo(path)

      ' Datei erzeugen und mit Daten füllen 
      Dim fs As New FileStream(path, FileMode.Create) 
      Dim bw As New BinaryWriter(fs) 
      bw.Write(500) 
      bw.Close()

      ' Datei binär auswerten 
      Dim byteDaten(CType(fi.Length, Integer)) As Byte 
      fs = New FileStream(path, FileMode.Open) 
      fs.Read(byteDaten, 0, CType(fi.Length, Integer)) 
      Console.Write("Als Byte-Array: ") 
      For Each b As Byte In byteDaten : Console.Write(b & " ") : Next 
      Console.WriteLine() 
      fs.Close()

      ' Datei als Text auswerten 
      Console.Write("Als Text: ") 
      Console.WriteLine(File.ReadAllText(path))

      File.Delete(path) 
      Console.ReadLine() 
    End Sub 
  End Module 
End Namespace

Das Lesen Byte für Byte mit der Methode Read von FileStream läuft völlig korrekt ab.

Als Byte-Array: 244 1 0 0 0

Wenn man das Originaldatenformat nicht kennt, gibt es keine Möglichkeit, um festzustellen, ob die Daten vier einzelne Bytes, zwei Short-Werten oder einen Integer repräsentieren (oder noch etwas ganz anderes). Zum Beispiel ist die Interpretation als Text nicht besonders überzeugend:

Als Text: ?

Schauen wir uns die Abbildung der vier Zahlen auf einen Integer an. Als Erstes müssen wir die richtige Reihenfolge berücksichtigen. Auf Intel-Prozessoren wird das niederwertigste Byte zuerst gespeichert (Little-Endian). Von groß nach klein sortiert ist die Bytefolge:

0 0 1 244

Das können wir direkt auf eine Bitfolge abbilden:

0000 0000 0000 0000 0000 0001 1111 0100

Die Kombination aller Bits ergibt tatsächlich die Dezimalzahl 500. Diese hardwareabhängige Konvertierung überlassen wir besser .NET und nutzen eine »passende« Methode:

Dim byteDaten(CType(fi.Length, Integer)) As Byte 
Dim br as New BinaryReader(fs) 
Console.WriteLine(br.ReadInt32())

Rheinwerk Computing - Zum Seitenanfang

7.6.4 Komplexe binäre Daten topZur vorigen Überschrift

Auch nicht-primitive Datentypen können binär geschrieben und gelesen werden, denn letztendlich setzen sie sich aus primitiven Typen zusammen, die in die richtige Struktur (Klasse/Objekt) eingebettet sind. Zur korrekten Handhabung komplexer Typen als Binärdaten müssen bekannt sein:

  • das Binärformat jedes primitiven Datentyps
  • die Reihenfolge der Daten im Strom
  • die Position jedes Datums im komplexen Typ als Funktion seiner Position im Strom

Da die beiden letzten Punkte für praktisch jede Anwendung verschieden sind, hat jedes Programm sein eigenes Binärdatenformat. Die Vorgehensweise bei der Behandlung solcher binärer Daten schauen wir uns am Beispiel einer einfachen Struktur an. Sie hat gegenüber einer Klasse den Vorteil, ein Werttyp zu sein, sodass wir nicht auch noch Referenzen auflösen müssen. So bleibt das Beispiel übersichtlicher, ohne seine Allgemeingültigkeit zu verlieren, denn die gezeigten Schritte lassen sich einfach auf beliebig komplexe andere Datentypen übertragen. Der Anschaulichkeit halber verwenden wir die Repräsentierung eines Punkts:


'...\IO\Ströme\Binärstruktur.vb

Structure Punkt 
  Public X, Y As Integer 
  Public Farbe As Long 
End Structure

Die ganzzahligen Datentypen sind bewusst verschieden gewählt, damit eine Behandlung als Integer-Array ausscheidet. Wir entwickeln eine Anwendung, die solche Punkte speichern kann und wahlfrei einen beliebigen Punkt auslesen kann. In der Datei stehen die Punkte einfach hintereinander. Die Information über deren Anzahl können wir auf zwei Arten erhalten:

  • Das Ende der Datei wird durch Daten markiert, die unmöglich ein Punkt sein können.
  • Am Anfang der Datei steht die Punktzahl.

Wir entscheiden uns für die zweite Variante (siehe Abbildung 7.4). Da alle Daten binär sind, muss auch das Format dieser Anzahl genau bekannt sein, damit jedes Byte in der Datei eine klare Zuordnung erhält. Im Folgenden wird diese Information in einem Integer gespeichert.

Abbildung 7.4 Datei mit drei gespeicherten Punkten

Die Auswertung der ersten vier Bytes liefert die Anzahl der gespeicherten Punkte, die folgenden insgesamt 16 Byte großen Blöcke beschreiben jeweils einen Punkt. Wir fassen die Methoden zur Handhabung in einem Modul namens Binärpunkte zusammen.

  • Speichern
  • Lesen

Die Methode Speichern bekommt als Parameter den Pfad zu einer Datei und ein Array mit den zu speichernden Punkten. Ein FileStream für diesen Pfad bildet die Basis eines BinaryWriter. Er schreibt zuerst die Anzahl Punkte binär in die Datei und dann in einer Schleife alle Punkte. Sie legt die Reihenfolge der Daten fest. Der Wert FileMode.Create für den Dateistrom garantiert, dass nur die in diesem Aufruf geschriebenen Daten in der Datei sind.


'...\IO\Ströme\Binärstruktur.vb

Sub Schreiben(ByVal pfad As String, ByVal punkte As Punkt()) 
  Dim fs As New FileStream(pfad, FileMode.Create) 
  Dim bw As New BinaryWriter(fs) 
  ' Anzahl der Punkte in die Datei schreiben 
  bw.Write(punkte.Length) 
  ' die Punkte in die Datei schreiben 
  For Each p As Punkt In punkte 
    bw.Write(p.X) : bw.Write(p.Y) : bw.Write(p.Farbe) 
  Next 
  bw.Close() 
End Sub

Mit der Schreibroutine liegt das Datenformat fest, und wir können die Leseroutine implementieren. Das Lesen erfolgt in derselben Reihenfolge wie das Schreiben:


'...\IO\Ströme\Binärstruktur.vb

Function Lesen(ByVal pfad As String) As Punkt() 
  Dim fs As New FileStream(pfad, FileMode.Open) 
  Dim br As New BinaryReader(fs) 
  '  die ersten 4 Bytes spezifizieren die Anzahl der Punkte 
  Dim anzahl As Integer = br.ReadInt32() 
  ' einlesen der Punkte 
  Dim punkte(anzahl – 1) As Punkt 
  For i As Integer = 0 To anzahl – 1 
    punkte(i).X = br.ReadInt32() : punkte(i).Y = br.ReadInt32() 
    punkte(i).Farbe = br.ReadInt64() 
  Next 
  br.Close() 
  Return punkte 
End Function

Da uns der Platzbedarf aller Daten bekannt ist, können wir an die richtige Position in der Datei springen und einen einzelnen Punkt einlesen. Um das Beispiel einfach zu halten, verzichte ich auf die Implementierung eigener Ausnahmeklassen.


'...\IO\Ströme\Binärstruktur.vb

Function Lesen(ByVal pfad As String, ByVal nr As Integer) As Punkt 
  Dim fs As New FileStream(pfad, FileMode.Open) 
  Dim pos As Integer = 4 + (nr – 1) * 16 
  Dim br As New BinaryReader(fs) 
  ' Ist die Position gültig? 
  If nr <= 0 Then Throw New ArgumentException("Punkt null gibt's nicht") 
  If nr > br.ReadInt32() Then Throw New ArgumentException("Zu groß") 
  ' Daten des gewünschten Points einlesen 
  fs.Seek(pos, SeekOrigin.Begin) 
  Dim p As New Punkt() 
  p.X = br.ReadInt32() : p.Y = br.ReadInt32():p.Farbe = br.ReadInt64() 
  br.Close() 
  Return p 
End Function

Am Dateianfang belegt die Punktzahl 4 Bytes, danach belegt jeder Punkt 16 Bytes. Damit haben wir die Position vor dem einzulesenden Punkt:

Dim pos As Integer = 4 + (nr – 1) * 16

Sie wird der Seek-Methode des BinaryReader übergeben:

fs.Seek(pos, SeekOrigin.Begin)

Damit ist unsere Klassendefinition fertig, und wir können abschließend die Implementierung testen. Dazu erzeugen wir ein Array mit zwei Testpunkten und speichern es mit Binärpunkte.Schreiben in eine Datei. Diese lesen wir mit Binärpunkte.Lesen aus und geben die gelesenen Punkte aus. Schließlich lesen wir einen Einzelpunkt und geben ihn aus.


'...\IO\Ströme\Binärstruktur.vb

Option Strict On 
Imports System.IO 
Namespace EA 
  Structure Punkt ... 
  Module Binärpunkte ...

  Module Binärstruktur 
    Sub Test() 
      Dim path As String = IO.Path.GetTempFileName()

      ' Testpunkte erzeugen 
      Dim punkte(1) As Punkt 
      punkte(0).X = 10 : punkte(0).Y = 20 : punkte(0).Farbe = 310 
      punkte(1).X = 40 : punkte(1).Y = 50 : punkte(1).Farbe = 110

      ' Punkte speichern 
      Binärpunkte.Schreiben(path, punkte)

      ' Punkte einlesen und ausgeben 
      For Each p As Punkt In Binärpunkte.Lesen(path) 
        Console.WriteLine("{{X={0}, Y={1}, Farbe={2}}}", p.X, p.Y, p.Farbe) 
      Next

      ' Einzelpunkt einlesen und ausgeben 
      Console.Write("Nummer des einzulesenden Punkts: ") 
      Dim nr As Integer = Convert.ToInt32(Console.ReadLine()) 
      Try 
        Dim p As Punkt = Binärpunkte.Lesen(path, nr) 
        Console.WriteLine("{{X={0}, Y={1}, Farbe={2}}}", p.X, p.Y, p.Farbe) 
      Catch ex As ArgumentException 
        Console.WriteLine("Fehler: {0}", ex.Message) 
      End Try

      File.Delete(path) 
      Console.ReadLine() 
    End Sub 
  End Module 
End Namespace

Die Ausgabe bestätigt die korrekte Implementierung:

{X=10, Y=20, Farbe=310} 
{X=40, Y=50, Farbe=110} 
Nummer des einzulesenden Punkts: 1 
{X=10, Y=20, Farbe=310}


Ihr Kommentar

Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen. >> Zum Feedback-Formular
<< zurück
  Zum Katalog
Zum Katalog: Visual Basic 2008
Visual Basic 2008
Jetzt bestellen


 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchempfehlungen
Zum Katalog: Visual Basic 2012






 Visual Basic 2012


Zum Katalog: Schrödinger programmiert C++






 Schrödinger
 programmiert C++


Zum Katalog: IT-Handbuch für Fachinformatiker






 IT-Handbuch für
 Fachinformatiker


Zum Katalog: Professionell entwickeln mit Visual C# 2012






 Professionell
 entwickeln mit
 Visual C# 2012


Zum Katalog: Windows Presentation Foundation






 Windows Presentation
 Foundation


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo




Copyright © Rheinwerk Verlag GmbH 2009
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


Nutzungsbestimmungen | Datenschutz | Impressum

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de