Streams


Serialization is the ability to read and write an arbitrary object graph (reading is sometimes called deserialization ). Before we can talk about serializing objects, we need to talk about where they're going serialized to.

Whenever an object is serialized, it must go somewhere. It may go into memory, a file, a database record, or a socket. Generally, where the data is actually written doesn't matter to the object itself. It needs to store the same data regardless of where it goes. All the object generally cares about is that bytes can be written and read, and sometimes we'd like to skip around among the bytes. To satisfy these desires, .NET provides the abstract base class Stream from the System.IO namespace:

 
 MustInherit Class Stream   Inherits MarshalByRefObject   Implements IDisposable   ' Properties   Public Property MustOverride ReadOnly CanRead() As Boolean   Public Property MustOverride ReadOnly CanSeek() As Boolean   Public Property MustOverride ReadOnly CanWrite() As Boolean   Public Property MustOverride ReadOnly Length() As Long   Public Property MustOverride ReadOnly Position() As Long   ' Methods   Public MustOverride Function BeginRead(...) As IAsyncResult   Public MustOverride Function BeginWrite(...) As IAsyncResult   Public MustOverride Sub Close()   Public MustOverride Function EndRead(asyncResult _ As IAsyncResult) As Integer   Public MustOverride Sub EndWrite(asynResult As IAsyncResult)   Public MustOverride Sub Flush()   Public MustOverride Function Read(buffer as Byte(), _ offset As Integer, count As Integer) As Integer   Public MustOverride Function ReadByte() As Integer   Public MustOverride Function Seek(offset As Long, _       origin As System.IO.SeekOrigin) As Long   Public MustOverride Sub SetLength(value As Long)   Public MustOverride Sub Write(buffer As Byte(), _ offset As Integer, count As Integer)   Public MustOverride Sub WriteByte(value As Byte) End Class 

.NET provides several classes that derive from Stream, including Memory-Stream, FileStream, and IsolatedStorageFileStream. The MemoryStream class is fun to play with because it has no permanent side effects:

 
 Imports System.IO ... Dim s As String = "Wahoo!" Dim n As Integer = 452 Dim mystream As Stream = New MemoryStream() ' Write to the stream Dim bytes1 As Byte() = UnicodeEncoding.Unicode.GetBytes(s) Dim bytes2 As Byte() = BitConverter.GetBytes(n) mystream.Write(bytes1, 0, bytes1.Length) mystream.Write(bytes2, 0, bytes2.Length) ' Reset the stream to the beginning mystream.Seek(0, SeekOrigin.Begin) ' Read from the stream Dim bytes3 As Byte() = New Byte(mystream.Length  4) Dim bytes4 As Byte() = New Byte(4) mystream.Read(bytes3, 0, bytes3.Length) mystream.Read(bytes4, 0, bytes4.Length) ' Do something with the data MsgBox(UnicodeEncoding.Unicode.GetString(bytes3) & " " & _   BitConverter.ToInt32(bytes4, 0)) mystream.Dispose() 

This code creates a specific implementation of the abstract Stream class, making sure to close it (even in the face of exceptions). The code then uses the stream for writing and reading bytes, being careful to seek back to the beginning of the stream in between these actions. We could have written exactly the same code for any stream.

However, the manual conversion of the string object back and forth between the bytes is kind of a pain. To avoid writing that code, we've got the StreamWriter and StreamReader classes:

 
 Dim s As String = "Wahoo!" Dim n As Integer = 452 Dim mystream As Stream = New MemoryStream() ' Write to the stream Dim writer As StreamWriter = New StreamWriter(mystream) writer.WriteLine(s) writer.WriteLine(n) writer.Flush() ' Flush the buffer ' Reset the stream to the beginning mystream.Seek(0, SeekOrigin.Begin) ' Read from the stream Dim reader As StreamReader = New StreamReader(mystream) Dim s2 As String = reader.ReadLine() Dim n2 As Integer = Integer.Parse(reader.ReadLine()) ' Do something with the data MsgBox(s2 & " " & n2) mystream.Dispose() 

This code is considerably simpler because the conversion to bytes is managed by the stream writer and readers as they work on the stream. However, the stream writer and readers are oriented toward text only, and that's why we wrote each piece of data on its own line and why we had to parse the integer back out of the string when reading. To avoid the conversion to and from strings, we can write the data in its native binary format using the BinaryWriter and BinaryReader classes:

 
 Dim s As String = "Wahoo!" Dim n As Integer = 452 Dim mystream As Stream = New MemoryStream() ' Write to the stream Dim writer As BinaryWriter = New BinaryWriter(mystream) Dim s2 As String = reader.ReadString() Dim n2 As Integer = reader.ReadInt32() ' Do something with the data MsgBox(s2 & " " & n2) mystream.Dispose() 

Using BinaryWriter and BinaryReader eliminates the need for string conversion, but our code still must keep track of the types of the objects we are writing and the order in which they must be read. We can group the data into a custom class and read it all at once, but BinaryWriter and BinaryReader don't support custom classes, only built-in simple types. To read and write arbitrary objects, we need a formatter.



Windows Forms Programming in Visual Basic .NET
Windows Forms Programming in Visual Basic .NET
ISBN: 0321125193
EAN: 2147483647
Year: 2003
Pages: 139

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net