|
|
|
|
||
|
||
|
.NET Streams Explained
by Wei-Meng Lee
04/14/2003
|
On of the common challenges facing beginning .NET programmers is the large number of classes in the .NET Class Library. Recently, I was working on a project involving file access. I was looking for the correct class to use for file handling and I realized that there are many classes in the System.IO namespace, each looking not much different from the others. And so, I set out to document some of the commonly used classes for performing regular file operations. The examples in the article are by no means exhaustive, but hopefully can help you in getting started with the right class!
Stream Class
A stream is an abstraction of a sequence of bytes. This sequence of bytes may come from a file, a TCP/IP socket, or memory. In .NET, a stream is represented, aptly, by the Stream class. The Stream class provides a generic view of a sequence of bytes. A Stream class forms the abstract class of all other streams. That is, you cannot directly create an instance of the Stream class. Instead, the Stream class is implemented by the following classes:
|
Streams fundamentally involve the following operations:
In this article, I will provide some examples to show the most commonly used classes for performing file I/O. In particular, I will use FileStream and MemoryStream, together with the File class for file creation, reading, and writing. I won’t be discussing each class in detail, as all of these details can be found from the excellent MSDN documentation that comes with Visual Studio .NET. Instead, I will just provide simple examples to illustrate the task that we are performing; the subheads of this article will be grouped by task.
All of the examples in this class make use of the following constants and variables:
Dim fs, s1, s2 As FileStream
Dim sr As StreamReader
Dim sw As StreamWriter
Dim br As BinaryReader
Dim bw As BinaryWriter
Dim ms As MemoryStream
Const FILE_NAME = "c:\textFile.txt"
Const BAK_FILE_NAME = "c:\textFile_bak.txt"
Const FILE_NAME_IMAGE = "c:\iMac.jpg"
Const FILE_NAME_BIN = "c:\bin.jpg"
Dim bytes(10) As Byte
Besides using FileStream and MemoryStream, I will also make use of the BinaryReader and BinaryWriter classes for reading and writing binary data, as well as the StreamReader and StreamWriter classes for reading and writing text data.
And since all of the classes discussed in this article fall under the System.IO namespace, I need to import it:
Imports System.IO
File Management
The File class allows you to create, delete, copy, and rename files. It also allows you to check if a file exists. The following example checks to see if a file exists, and if it does, makes a copy of the file and then deletes the original.
'---Copy and Delete the file
If File.Exists(FILE_NAME) Then
File.Copy(FILE_NAME, BAK_FILE_NAME, True)
File.Delete(FILE_NAME)
End If
File Creation
You can use the File class to create new files as well as open files for reading. The following example first creates a file and returns a FileStream object. It then creates a new text file and returns a StreamWriter object. Lastly, it illustrates that you can open a file for reading or writing using the Open() method from the File class.
fs = File.Create(FILE_NAME_BIN)
fs.Close()
sw = File.CreateText(FILE_NAME)
sw.Close()
fs = File.Open(FILE_NAME, FileMode.Open, FileAccess.Read, FileShare.Read)
fs.Close()
Writing Binary Data Using the FileStream Class
To write binary data to a file, you can use the FileStream class. The following example uses the FileStream class to create a new file for writing. It then writes 11 bytes to the file and closes it.
'---create a file and write some bytes to it
fs = New FileStream(FILE_NAME, FileMode.CreateNew, FileAccess.Write)
bytes(0) = 72 'H'
bytes(1) = 101 'e'
bytes(2) = 108 'l'
bytes(3) = 108 'l'
bytes(4) = 111 'o'
bytes(5) = 13 'CR'
bytes(6) = 87 'W'
bytes(7) = 111 'o'
bytes(8) = 114 'r'
bytes(9) = 108 'l'
bytes(10) = 100 'd'
fs.Write(bytes, 0, bytes.Length)
fs.Close()
Writing Text Using a StreamWriter Class
For writing text to a file, it is easier to use the StreamWriter class. The following example shows how to use the StreamWriter class to write a string of text to a file.
'---Using a streamWriter to write to a file
sw = New StreamWriter(FILE_NAME, True, System.Text.Encoding.ASCII)
sw.WriteLine("Welcome to VB.NET")
sw.Close()
Reading Binary Data Using the FileStream Class
To read binary data from a file, use the FileStream class. The following example opens a file and reads the binary data. The bytes read are then converted to ASCII characters and printed to the Output window.
'---open a file and read the byte(s) out
fs = New FileStream(FILE_NAME, FileMode.Open, FileAccess.Read)
fs.Read(bytes, 0, bytes.Length)
Dim i As Short
For i = 0 To bytes.Length - 1
Console.Write(Chr(bytes(i)))
Next
Seeking
Stream objects can support seeking. The following example shows a FileStream object advancing 11 bytes and then starting to read the next six bytes.
'---seeking
fs.Seek(11, SeekOrigin.Current)
fs.Read(bytes, 0, 6)
For i = 0 To 5
Console.Write(Chr(bytes(i)))
Next
fs.Close()
Reading Text Using the StreamReader Class
When reading text files, you can use the StreamReader class. The following example uses a StreamReader object to open a file for reading. The file is read line by line, and each line is printed to the Output window.
'---open a file and read line by line using a streamreader
sr = New StreamReader(FILE_NAME)
Dim line As String = sr.ReadLine()
While Not line Is Nothing
Console.Write(line)
line = sr.ReadLine()
End While
sr.Close()
Reading and Writing Binary Data Using the BinaryReader and BinaryWriter Classes
Besides using the FileStream class for reading and writing binary data, you can also use the BinaryReader and BinaryWriter classes. The following example reads the binary data from one file and writes it into another, essentially making a copy of the file. It first uses the FileStream class to open two files--one for reading and one for writing. The BinaryReader class is then used to read the binary data from the FileStream, and the BinaryWriter is used to write the binary data to the file.
'---read from and write to a binary file
s1 = New FileStream(FILE_NAME_IMAGE, FileMode.Open, FileAccess.Read)
s2 = New FileStream("c:\iMac_copy.jpg", FileMode.CreateNew, FileAccess.Write)
br = New BinaryReader(s1)
bw = New BinaryWriter(s2)
Dim byteRead As Byte
Dim j As Integer
For j = 0 To br.BaseStream.Length() - 1
byteRead = br.ReadByte
bw.Write(byteRead)
Next
br.Close()
bw.Close()
Writing Binary Data to a MemoryStream Class
Sometimes you need to load binary data from file and save it in memory for other uses. A good example is the PictureBox control in a Windows form. The following example shows how the BinaryReader class is used to read binary data from a file and then write it to a MemoryStream object. The PictureBox control then uses the data contained in the MemoryStream as a bitmap image.
'--read from a binary stream and write into a memory stream
s1 = New FileStream(FILE_NAME_IMAGE, FileMode.Open, FileAccess.Read)
ms = New MemoryStream(s1.Length)
br = New BinaryReader(s1)
Dim bytesRead As Byte() = br.ReadBytes(s1.Length)
ms.Write(bytesRead, 0, s1.Length)
PictureBox1.Image = New Bitmap(ms)
Some Useful Functions
Sometimes you may want to convert a string into a byte array, or vice versa, especially when you are using the Cryptographic APIs. I have provided three functions here to help you make the conversions. The three functions are:
Public Function stringcharToByteArray(ByVal str As String) As Byte()
'e.g. "abcdefg" to {a,b,c,d,e,f,g}
Dim s As Char()
s = str.ToCharArray
Dim b(s.Length - 1) As Byte
Dim i As Integer
For i = 0 To s.Length - 1
b(i) = Convert.ToByte(s(i))
Next
Return b
End Function
Public Function stringToByteArray(ByVal str As String) As Byte()
' e.g. "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16" to
'{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}
Dim s As String()
s = str.Split(" ")
Dim b(s.Length - 1) As Byte
Dim i As Integer
For i = 0 To s.Length - 1
b(i) = Convert.ToByte(s(i))
Next
Return b
End Function
Public Function byteArrayToString(ByVal b() As Byte) As String
Dim i As Integer
Dim s As New System.Text.StringBuilder()
For i = 0 To b.Length - 1
Console.WriteLine(b(i))
If i <> b.Length - 1 Then
s.Append(b(i) & " ")
Else
s.Append(b(i))
End If
Next
Return s.ToString
End Function
Wei-Meng Lee , http://weimenglee.blogspot.com, is a technologist and founder of Developer Learning Solutions, a technology company specializing in hands-on training on the latest Microsoft technologies.