VB.NET-Tipp 0101: Stream-Konzepte
von Spatzenkanonier
Beschreibung
Lese- und Schreibvorgänge aller Art werden unter Visual Basic .NET vorzugsweise mittels Streams verwaltet. Je nach Bedarf gibt es deren sehr viele, drei grundlegende Konzepte teilen sie jedoch miteinander:
1) Die Daten können portionsweise gelesen beziehungsweise geschrieben werden. Das ermöglicht unendlich große Datenmengen zu bewegen, ohne einen entsprechend unendlich großen Zwischenspeicher vorhalten zu müssen. Essentiell sind daher die gezeigte(n) Schleife(n) zum gepufferten Kopieren eines Streams in einen anderen.
2) Streams verschiedenster Art können aufeinander aufgesetzt werden, wodurch die Ausgabe des einen Streams direkt zur Eingabe des anderen wird. Diese Eigenschaft ist wichtig zum Bau von Konvertern - es können viele Verarbeitungsschritte hintereinander geschaltet werden (s. Pipes and Filters ).
3) Zu erwähnen wären noch die verschiedenen Reader und Writer, die ebenfalls aufgesetzt werden können, und quasi als "Adapter" zur letztendlichen Datenverarbeitung funktionieren.
Die Kompatiblität der Streams erleichtert es sehr wiederverwendbaren Code zu schreiben: Würde man wie in diesem Beispiel statt der Filestreams NetworkStreams anschließen, so könnte man dieselben Daten ebensogut über das Internet verschicken.
Schwierigkeitsgrad: | Framework-Version(en): .NET Framework 2.0, .NET Framework 3.0, .NET Framework 3.5 | .NET-Version(en): Visual Basic 2008 | Download: |
' Dieser Quellcode stammt von http://www.activevb.de ' und kann frei verwendet werden. Für eventuelle Schäden ' wird nicht gehaftet. ' Um Fehler oder Fragen zu klären, nutzen Sie bitte unser Forum. ' Ansonsten viel Spaß und Erfolg mit diesem Source! ' Projektversion: Visual Studio 2008 ' Option Strict: An ' Option Infer: An ' ' Referenzen: ' - System ' - System.Core ' - System.Data ' - System.Data.DataSetExtensions ' - System.Deployment ' - System.Drawing ' - System.Windows.Forms ' - System.Xml ' ' Imports: ' - Microsoft.VisualBasic ' - Microsoft.VisualBasic.ControlChars ' - System ' - System.Collections.Generic ' - System.Data ' - System.Diagnostics ' - System.Linq ' - System.Windows.Forms ' ' ############################################################################## ' ################################# Form1.vb ################################### ' ############################################################################## Imports System.IO Public Class Form1 Private Sub MenuItem_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles _ btZipWordDoc.Click, btUnzipWordDoc.Click, btShowDocuments.Click, _ btStoreControls.Click, btRestoreControls.Click Select Case True Case sender Is btZipWordDoc modGZip.Zip("Test.doc", "Test.gzip") Case sender Is btUnzipWordDoc modGZip.UnZip("Test.gzip", "Test2.doc") Case sender Is btShowDocuments Process.Start("Test.doc") Process.Start("Test2.doc") Case sender Is btStoreControls ' Zum Schreiben einen (Binary-)Writer auf einen Stream aufsetzen Using fs As New FileStream("data.dat", FileMode.Create), _ writer As New BinaryWriter(fs) writer.Write(CheckBox1.Checked) writer.Write(TextBox1.Text) writer.Write(NumericUpDown1.Value) writer.Write(DateTimePicker1.Value.Ticks) End Using Case sender Is btRestoreControls ' Zum Lesen einen (Binary-)Reader auf einen Stream aufsetzen Using fs As New FileStream("data.dat", FileMode.Open), _ reader As New BinaryReader(fs) CheckBox1.Checked = reader.ReadBoolean TextBox1.Text = reader.ReadString NumericUpDown1.Value = reader.ReadDecimal DateTimePicker1.Value = Date.FromBinary(reader.ReadInt64) End Using End Select My.Computer.Audio.PlaySystemSound(Media.SystemSounds.Asterisk) End Sub End Class ' ############################################################################## ' ################################ modGZip.vb ################################## ' ############################################################################## Imports System.IO Imports System.IO.Compression Public Module modGZip Public Sub Zip(ByVal src As String, ByVal dest As String) ' Durch Zwischenschalten des GZipStreams wird aus einem Kopier-Vorgang ' eine GZip-Konvertierung (die komprimierte Datei ist nicht ' Zip-kompatibel) Using readStream As New FileStream(src, FileMode.Open), _ writeStream As New FileStream(dest, FileMode.Create), _ zipper As New GZipStream(writeStream, CompressionMode.Compress) ' (Puffer zum Testen absurd klein gewählt) Dim bufSize As Integer = Byte.MaxValue Dim buf(bufSize - 1) As Byte ' Standard-Kopier-Schleife für Streams mit festgelegtem Ende Do bufSize = readStream.Read(buf, 0, bufSize) zipper.Write(buf, 0, bufSize) ' Schleife endet, wenn Puffer nicht ganz befüllt wurde Loop Until bufSize < buf.Length End Using End Sub Public Sub UnZip(ByVal src As String, ByVal dest As String) ' Rück-Konvertierung. Beachte, daß hier der GZipStream auf dem Read- ' Stream aufsitzt, und mit CompressionMode.Decompress erstellt ist. Using readStream As New FileStream(src, FileMode.Open), _ unZipper As New GZipStream(readStream, _ CompressionMode.Decompress), _ writeStream As New FileStream(dest, FileMode.Create) ' Verwendung der in die Extension-Methode ausgelagerten Kopier- ' Schleife unZipper.WriteTo(writeStream) End Using End Sub End Module ' ############################################################################## ' ################################ StreamX.vb ################################## ' ############################################################################## Imports System.Runtime.CompilerServices Imports System.IO Public Module StreamX ''' <summary> Kopiert von einem Stream in einen Anderen </summary> ''' <remarks> ''' Es gibt Streams ohne festgelegtes Ende (z.B. NetworkStream). ''' In solchem Fall **muss** 'count' angegeben werden. ''' </remarks> <Extension()> _ Public Sub WriteTo( _ ByVal readStream As Stream, _ ByVal writeStream As Stream, _ Optional ByVal count As Long = -1, _ Optional ByVal bufSize As Integer = Short.MaxValue) Dim buf(bufSize - 1) As Byte If count < 0 AndAlso readStream.CanSeek Then count = readStream.Length - readStream.Position End If If count < 0 Then ' Durch 0-Byte-Lesevorgang terminierte Kopier-Schleife ' Ein NetworkStream würde ein Timeout-Problem verursachen Do Dim portion = readStream.Read(buf, 0, bufSize) If portion = 0 Then Return writeStream.Write(buf, 0, portion) Loop Else ' Zählergesteuerte Kopier-Schleife Do If count < bufSize Then bufSize = CInt(count) Dim portion = readStream.Read(buf, 0, bufSize) If portion = 0 Then Throw New ArgumentException("Die " & _ "angegebene Anzahl Bytes konnte nicht aus dem Lese-", _ "Stream gelesen werden readStream + count") count -= portion writeStream.Write(buf, 0, portion) Loop Until count = 0 End If End Sub End Module
Ihre Meinung
Falls Sie Fragen zu diesem Artikel 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.