Reading and Writing Binary Data


So far, we have just been reading and writing bytes or characters, but it is possible—indeed, common—to read and write other types of data. For example, you might want to create a file that contains ints, doubles, or shorts. To read and write binary values of the C# built-in types, you will use BinaryReader and BinaryWriter. When using these streams, it is important to understand that this data is read and written using its internal, binary format, not its human-readable text form.

BinaryWriter

A BinaryWriter is a wrapper around a byte stream that manages the writing of binary data. Its most commonly used constructor is shown here:

 BinaryWriter(Stream outputStream)

Here, outputStream is the stream to which data is written. To write output to a file, you can use the object created by FileStream for this parameter. If outputStream is null, then an ArgumentNullException is thrown. If outputStream has not been opened for writing, ArgumentException is thrown.

BinaryWriter defines methods that can write all of C#’s built-in types. Several are shown in Table 14-5. Notice that a string is written using its internal format, which includes a length specifier. BinaryWriter also defines the standard Close( ) and Flush( ) methods, which work as described earlier.

Table 14-5: Commonly Used Output Methods Defined by BinaryWriter

Method

Description

void Write(sbyte val)

Writes a signed byte.

void Write(byte val)

Writes an unsigned byte.

void Write(byte[ ] buf)

Writes an array of bytes.

void Write(short val)

Writes a short integer.

void Write(ushort val)

Writes an unsigned short integer.

void Write(int val)

Writes an integer.

void Write(uint val)

Writes an unsigned integer.

void Write(long val)

Writes a long integer.

void Write(ulong val)

Writes an unsigned long integer.

void Write(float val)

Writes a float.

void Write(double val)

Writes a double.

void Write(char val)

Writes a character.

void Write(char[ ] buf)

Writes an array of characters.

void Write(string val)

Writes a string using its internal representation, which includes a length specifier.

BinaryReader

A BinaryReader is a wrapper around a byte stream that handles the reading of binary data. Its most commonly used constructor is shown here:

 BinaryReader(Stream inputStream)

Here, inputStream is the stream from which data is read. To read from a file, you can use the object created by FileStream for this parameter. If inputStream has not been opened for reading, ArgumentException is thrown.

BinaryReader provides methods for reading all of C#’s value types. Several commonly used methods are shown in Table 14-6. Notice that ReadString( ) reads a string that is stored using its internal format, which includes a length specifier. All methods throw an EndOfStreamException when the end of the stream has been encountered. They throw an IOException if an error occurs. BinaryReader also defines three versions of Read( ), which are shown here:

int Read( )

Returns an integer representation of the next available character from the invoking input stream. Returns 1 when attempting to read at the end of the file.

int Read(byte[ ] buf, int offset, int num)

Attempts to read up to num bytes into buf starting at buf[offset], returning the number of bytes successfully read.

int Read(char[ ] buf, int offset, int num)

Attempts to read up to num characters into buf starting at buf[offset], returning the number of characters successfully read.

Table 14-6: Commonly Used Input Methods Defined by BinaryReader

Method

Description

bool ReadBoolean( )

Reads a bool.

byte ReadByte( )

Reads a byte.

sbyte ReadSByte( )

Reads an sbyte.

byte[ ] ReadBytes(int num)

Reads num bytes and returns them as an array.

char ReadChar( )

Reads a char.

char[ ] ReadChars(int num)

Reads num characters and returns them as an array.

double ReadDouble( )

Reads a double.

float ReadSingle( )

Reads a float.

short ReadInt16( )

Reads a short.

int ReadInt32( )

Reads an int.

long ReadInt64( )

Reads a long.

ushort ReadUInt16( )

Reads a ushort.

uint ReadUInt32( )

Reads a uint.

ulong ReadUInt64( )

Reads a ulong.

string ReadString( )

Reads a string that is represented in its internal, binary format, which includes a length specifier. This method should only be used to read a string that has been written using a BinaryWriter.

These methods will throw an IOException on failure. Other exceptions are possible.

Also defined is the standard Close( ) method.

Demonstrating Binary I/O

Here is a program that demonstrates BinaryReader and BinaryWriter. It writes and then reads back various types of data to and from a file.

 // Write and then read back binary data. using System; using System.IO; class RWData {   public static void Main() {     BinaryWriter dataOut;     BinaryReader dataIn;     int i = 10;     double d = 1023.56;     bool b = true;     try {       dataOut = new         BinaryWriter(new FileStream("testdata", FileMode.Create));     }     catch(IOException exc) {       Console.WriteLine(exc.Message + "\nCannot open file.");       return;     }     try {       Console.WriteLine("Writing " + i);       dataOut.Write(i);       Console.WriteLine("Writing " + d);       dataOut.Write(d);       Console.WriteLine("Writing " + b);       dataOut.Write(b);       Console.WriteLine("Writing " + 12.2 * 7.4);       dataOut.Write(12.2 * 7.4);     }     catch(IOException exc) {       Console.WriteLine(exc.Message + "\nWrite error.");     }     dataOut.Close();     Console.WriteLine();     // Now, read them back.     try {       dataIn = new           BinaryReader(new FileStream("testdata", FileMode.Open));     }     catch(FileNotFoundException exc) {       Console.WriteLine(exc.Message + "\nCannot open file.");       return;     }     try {       i = dataIn.ReadInt32();       Console.WriteLine("Reading " + i);       d = dataIn.ReadDouble();       Console.WriteLine("Reading " + d);       b = dataIn.ReadBoolean();       Console.WriteLine("Reading " + b);       d = dataIn.ReadDouble();       Console.WriteLine("Reading " + d);     }     catch(IOException exc) {       Console.WriteLine(exc.Message + "Read error.");     }     dataIn.Close();   } }

The output from the program is shown here:

 Writing 10 Writing 1023.56 Writing True Writing 90.28 Reading 10 Reading 1023.56 Reading True Reading 90.28

If you examine the testdata file produced by this program, you will find that it contains binary data, not human-readable text.

Here is a more practical example that shows how powerful binary I/O is. The following program implements a very simple inventory program. For each item in the inventory, the program stores the item’s name, the number on hand, and its cost. Next, the program prompts the user for the name of an item. It then searches the database. If the item is found, the inventory information is displayed.

 /* Use BinaryReader and BinaryWriter to implement    a simple inventory program. */ using System; using System.IO; class Inventory {   public static void Main() {     BinaryWriter dataOut;     BinaryReader dataIn;     string item; // name of item     int onhand;  // number on hand     double cost; // cost     try {       dataOut = new         BinaryWriter(new FileStream("inventory.dat",                                     FileMode.Create));     }     catch(IOException exc) {       Console.WriteLine(exc.Message + "\nCannot open file.");       return;     }     // Write some inventory data to the file.     try {       dataOut.Write("Hammers");       dataOut.Write(10);       dataOut.Write(3.95);       dataOut.Write("Screwdrivers");       dataOut.Write(18);       dataOut.Write(1.50);       dataOut.Write("Pliers");       dataOut.Write(5);       dataOut.Write(4.95);       dataOut.Write("Saws");       dataOut.Write(8);       dataOut.Write(8.95);     }     catch(IOException exc) {       Console.WriteLine(exc.Message + "\nWrite error.");     }     dataOut.Close();     Console.WriteLine();     // Now, open inventory file for reading.     try {       dataIn = new           BinaryReader(new FileStream("inventory.dat",                        FileMode.Open));     }     catch(FileNotFoundException exc) {       Console.WriteLine(exc.Message + "\nCannot open file.");       return;     }     // Look up item entered by user.     Console.Write("Enter item to look up: ");     string what = Console.ReadLine();     Console.WriteLine();     try {       for(;;) {         // Read an inventory entry.         item = dataIn.ReadString();         onhand = dataIn.ReadInt32();         cost = dataIn.ReadDouble();         /* See if the item matches the one requested.            If so, display information */         if(item.CompareTo(what) == 0) {           Console.WriteLine(onhand + " " + item + " on hand. " +                             "Cost: {0:C} each", cost);           Console.WriteLine("Total value of {0}: {1:C}." ,                             item, cost * onhand);           break;         }       }     }     catch(EndOfStreamException) {       Console.WriteLine("Item not found.");     }     catch(IOException exc) {       Console.WriteLine(exc.Message + "Read error.");     }     dataIn.Close();   } }

Here is a sample run:

 Enter item to look up: Screwdrivers 18 Screwdrivers on hand. Cost: $1.50 each Total value of Screwdrivers: $27.00.

In the program, notice how inventory information is stored in its binary format. Thus, the number of items on hand and the cost are stored using their binary format rather than their human-readable text-based equivalents. This makes it possible to perform computations on the numeric data without having to convert it from its human-readable form.

There is one other point of interest in the inventory program. Notice how the end of the file is detected. Since the binary input methods throw an EndOfStreamException when the end of the stream is reached, the program simply reads the file until either it finds the desired item or this exception is generated. Thus, no special mechanism is needed to detect the end of the file.




C# 2.0(c) The Complete Reference
C# 2.0: The Complete Reference (Complete Reference Series)
ISBN: 0072262095
EAN: 2147483647
Year: 2006
Pages: 300

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