File Handling in
File Handling in
.NET programs perform I/O through streams. A stream is an abstraction which either produces or consumes information. Alternatively, we can say that streams represent a sequence of bytes going to or coming from a storage medium (such as a file) or a physical or virtual device (network port or inter-process communication pipe). All streams behave in the same manner, even if the actual devices they are linked to may differ, which means we are going to use the same methods to write data to a standard output device as a disk file.
Predefined Steams
We have three predefined streams in .NET which can be redirected to any compatible I/O device.
Console.Out
-> Represents the output stream associated with standard Output -> Represents the output stream associated with standard Error -> Represents the input stream associated with standard Input device.
device.
Console.Err
device.
Console.In
We have to import the required classes into our application for performing I/O operations.
Imports System.IO -> Namespace containing all I/O classes. Stream Class -> This class represents a byte stream and is a base class for all other stream classes. As it is an abstract class we can instantiate it but it gives the information about a set of standard stream operations. Close() -> Closes the stream. Flush() -> Flushes the stream to push any data present in the stream to the destination. ReadByte() -> Reads one byte of data from the input source and returns the integer representing that byte. If not successful it returns a value 1. ReadBytes(Byte(),offset,noofbytes) -> Tries to read noofbytes of the input source and stores them in the byte array. It returns an integer stating how many bytes actually read.
Seek(offset,SeekOrigin)
the stream.
WriteByte(Byte) -> Tries to write one byte to the output. WriteBytes(Byte(),position,noofbytes) -> Tries to write noofbytes
Exceptions
IOException: This exception is generated when an I/O operation fails. NotSupportedException: This exception is generated when we attempt to
perform an invalid operation not supported by the stream. Before performing any operations through streams we can test for its support using CanRead(), CanSeek(), CanWrite() methods. We can also use the other properties as Length and Position for knowing the length and pointer position respectively. Concept of Flush When the file output is performed, data is often not immediately written to the actual physical device. Instead, the output is buffered by the O/S until a sizable chunk is obtained which is written all at once. If we can cause data to be written to the physical device whether the buffer is full or not we call the Flush() method, and this improves efficiency. Similarly, when we finished up writing to an output destination we should close the stream by using Close() which ensures data preset in buffer written to the physical device.
ByteStream Classes
1. FileStream: This represents byte stream for File I/O. 2. MemoryStream: Byte Stream that uses memory for storage. 3. BufferedStream: Wraps a byte stream and adds buffering.
CharacterStreams Classes
To create a character stream we use the .NET character stream wrappers which wrap a byte stream within themselves. We can perform character based I/O using these character streams. The abstract classes in this category are TextReader and TextWriter. Methods Supported by TextReader
ReadLine()
-> Returns a string containing one line of data read from the input
source. -> Tries to see and know whether next character is available in the input stream or not. It returns 1 in case the next character is not available. Read() -> Reads a character and returns 1 for non availability.
Peek() Read(Char(),position,noofchars)
ReadBlock(Char(),position,noofchars) ReadToEnd() ->Returns a string containing data from current position to the end of
physical medium. We will use classes like StreamReader, StreamWriter, StringReader and StringWriter.
BinaryStream Classes
These classes provide the functionality of reading and writing binary data directly.
FileStream: To create a byte stream linked
to a file we use the file stream class. We can perform both read and write operations using this class.
'Constructor: FileStream(String Filename,FileMode,FileAccess)
FileMode
Append: opens the file if it exists
file.
Create: Will create a new file for writing, if it exists it will be overwritten. CreateNew: Will create a new file, throws exception if the file already exists. OpenOrCreate: Opens the file if exists or create the file. Open: Opens the file reading or writing if exists or throws FileNotFoundException Truncate: Opens the existing file and reduces its length to zero.
FileAccess
Read: Provides Read Access to the File. Write: Provides Write Access to the File. ReadWrite: Provides Read and write access to the file.
Example of FileStream
1. Reading Data
Dim fs As FileStream = New FileStream("a.txt", FileMode.Open, FileAccess.Read) Dim i As Integer Dim str As String = "" i = fs.ReadByte() While i <> -1 str += Chr(i) i = fs.ReadByte() End While fs.Close() TextBox1.Text = str
2. Writing Data
Dim fs As FileStream = New FileStream("a.txt", FileMode.Create, FileAccess.Write) Dim arr() As Char = TextBox1.Text.ToCharArray() Dim c As Char For Each c In arr fs.WriteByte(Asc(c)) Next fs.Close()
2. Writing Data
Dim fs As New FileStream("stream.txt", FileMode.Create, FileAccess.Write) Dim swriter As New StreamWriter(fs) swriter.Write(TextBox1.Text) swriter.Close()
In this context, "native format" means the actual bits are used to store the value in memory. The data is read and written using its internal binary format, not its human readable text format. We must create a Stream object explicitly and pass it to the constructor method of either the BinaryReader or the BinaryWriter class. These classes provide a wrapper around the byte stream which manages the reading and writing of binary data. Working with the BinaryWriter object is especially simple because its Write method is overloaded to accept all the primitive .NET types, including signed and unsigned integers; Single, Double, and String values; and so on. The BinaryReader class exposes many Readxxxx methods, one for each possible native data type, and a PeekChar method that returns -1 at the end of the stream. Outputting strings with a BinaryWriter requires some additional care, however. Passing a string to the Write method outputs a length-prefixed string to the stream. If you want to write only the actual characters (as often happens when you're working with fixed-length strings), you must pass the Write method an array of chars. The Write method is overloaded to take additional arguments that specify which portion of the array should be written. Reading back strings requires different techniques as well, depending on how the string was written. You use the ReadString method for length-prefixed strings and the ReadChars method for fixed-length strings.
Reading Data
Dim fs As New FileStream("binary.txt", FileMode.OpenOrCreate, FileAccess.Read) Dim breader As New BinaryReader(fs) breader.BaseStream.Seek(0, SeekOrigin.Begin) Dim a As Integer = breader.ReadInt32() Dim t As Char = breader.ReadChar() Dim s As Single = breader.ReadSingle() Dim str As String = breader.ReadString() TextBox1.Text = a & vbCrLf & t & vbCrLf & s & vbCrLf & str breader.Close()
Writing Data
FileOpen(10, "myfile.txt", OpenMode.Output) PrintLine(10, TextBox1.Text) FileClose(10) MsgBox("Data Saved")
Reading Data
FileOpen(78, "myfile.txt", OpenMode.Input) While Not EOF(78) TextBox1.Text += LineInput(78) & vbCrLf End While FileClose(78)
Using Structures
Structure student Dim roll As Integer Dim nm As String Public Sub New(ByVal r As Integer, ByVal n As String) roll = r nm = n End Sub Public Sub display() MsgBox("The values are " & roll & Space(5) & nm) End Sub End Structure
Writing Structures
Dim s1 As New student(10, "Ashok") FileOpen(10, "struct.txt", OpenMode.Binary) FilePut(10, s1) FileClose(10) MsgBox("Structure saved")
Reading Structures
Dim s2 As New student FileOpen(100, "struct.txt", OpenMode.Binary) FileGet(100, s2) s2.display() FileClose(100)
Serialization and persistence are often used as synonyms, so you can also say that an object is persisted and depersisted. The MSDN documentation makes a distinction, however, and uses persistence to mean that the data is stored in a durable medium, such as a file or a database field, while serialization can be applied to objects stored in nondurable media, such as memory buffers. The .NET Framework knows how to serialize all basic data types, including numbers, strings, and arrays of numbers and strings, so you can save and reload these types to and from a file stream (or any other type of stream) with minimal effort. All we need to serialize and deserialize a basic object is the use of a proper formatter object. Formally speaking, a formatter is an object that implements the IFormatter interface (defined in the System.Runtime.Serialization namespace). 1. The BinaryFormatter object, defined in provides an efficient way to persist an object in a compact binary format. In practice, the actual bits in memory are persisted, so the serialization and deserialization processes are very fast. 2. The SoapFormatter object, defined in System.Runtime.Serialization.Formatters. SOAP namespace, persists data in human-readable XML format, following the Simple Object Access Protocol (SOAP) specifications. The serialization and deserialization processes are somewhat slower than with the BinaryFormatter object. On the other hand, data can be sent easily to another application through HTTP and displayed in a humanreadable format.
System.Runtime.Serialization.Formatters. Binary namespace,
Binary Serialization
The key methods that all formatter objects support are Serialize and Deserialize, whose purpose is rather evident. The Serialize method takes a Stream object as its first argument and the object to be serialized as its second argument:
'Create an array of integers. Dim arr() As Integer = {1, 2, 4, 8, 16, 32, 64, 128, 256} ' Open a file stream for output. Dim fs As FileStream = New FileStream("ser.dat", FileMode.Create) ' Create a binary formatter for this stream. Dim bf As New BinaryFormatter() ' Serialize the array to the file stream, and flush the stream. bf.Serialize(fs, arr) fs.Close()
Reading back the file data and deserializing it into an object requires the Deserialize function, which takes the input Stream as its only argument and returns an Object value, which must be cast to a properly typed variable:
'Open a file stream for input.
Dim fs As FileStream = New FileStream("ser.dat", FileMode.Open) ' Create a binary formatter for this stream. Dim bf As New BinaryFormatter() ' Deserialize the contents of the file stream into an Integer array. ' Deserialize returns an object that must be coerced. Dim arr() As Integer = CType(bf.Deserialize(fs), Integer()) ' Display the result. For Each n As Integer In arr Console.Write(n.ToString & " ") Next
SOAP Serialization
You can change the serialization format to SOAP by simply using another formatter object, the SoapFormatter. This namespace isn't available in the default Visual Basic console project, so you have to click Add Reference on the Project menu in Visual Studio to add the System.Runtime.Serialization.Formatters.Soap.dll library to the list of libraries that appears in the Object Browser. Note that the SoapFormatter's constructor is passed a StreamingContext object that specifies where the serialization data is stored:
' Serialize an object to a file in SOAP format. Sub SaveSoapData(ByVal o As Object) ' Open a file stream for output. Dim fs As FileStream = New FileStream("soap.xml", FileMode.Create) ' Create a SOAP formatter for this file stream. Dim sf As New SoapFormatter(Nothing, New StreamingContext( StreamingContextStates.File)) ' Serialize the array to the file stream, and close the stream. sf.Serialize(fs, o) fs.Close() End Sub ' Deserialize an object from a file in SOAP format. Function LoadSoapData() As Object ' Open a file stream for input. Dim fs As FileStream = New FileStream("soap.xml", FileMode.Open) ' Create a SOAP formatter for this file stream. Dim sf As New SoapFormatter(Nothing, New StreamingContext(StreamingContextStates.File)) ' Deserialize the contents of the stream into an object and close the stream. LoadSoapData = sf.Deserialize(fs) fs.Close() End Function
To make a user-defined class Serializable we have to use <Serializable()> attribute for a class as:
<Serializable()> Class SerClass Public x,y as Integer Public Sub New() x=10 y=20
To Serialize
Dim fs As FileStream = New FileStream("obj.dat", FileMode.Create) Dim bf As New BinaryFormatter() ' Serialize the class to the file stream, and flush the stream. bf.Serialize(fs, New SerClass()) fs.Close()
To Deserialize
Dim fs As FileStream = New FileStream("obj.dat", FileMode.Open) Dim bf As New BinaryFormatter() ' Deserialize the contents of the file stream into an Integer array. ' Deserialize returns an object that must be coerced. Dim o As SerClass = CType(bf.Deserialize(fs), SerClass) MsgBox(o.x & Space(5) & o.y)