Reading and writing to and from binary files can be done using the FileStream class.
(Note that if you are working with the .NET Framework 1.x, this will most likely be the case.)
The FileStream Class
A FileStrearn instance is used to read or write data to or from a file.
In order to construct a FileStream, you need four pieces of information:
- The file you want to access.
- The mode, which indicates how you want to open the file for an existing file? And if you are opening and existing file, should any right operation be interpreted as overwriting the content of the file?
- The access, which indicates how you want to access the file For example, do you want to To read from or write to the file or do both?
4. The share access, which specifies whether you want exclusive access to the file.
Or, are you access the rile simultaneously? If so, should other streams have access to read the file to write to it, or to do both?.
The first of these pieces of information is usually represented by a string that contains the full path name in the file, and this chapter consider, only those constructors that require a string here.
Resides those constructors, however, some additional (ones takes an old Windows:-APT-styleWindows handle to a file instead.
The remaining three pieces of information are represented by three .NET’enumerations called FileMode, FileAccess, and FileShare.
The values of these enumerations are listed in the following’ table; they should be self-explanatory.
FileMode: Append,Create, CreateNew, Open,OpenOrCreate, or Truncate
FileAccess: Read,ReadWrite,or Write
FileShare: Delete,Inheritable,None,Read,ReadWrite,or Write
Note that in the case of FileMode, exceptions can be thrown if you request a mode that is inconsistent with the existing status of the file.
Append, Open, and Truncate will throw an exception if the file does not already exist, and CreateNew will throw an exception if it does.
Create and OpenOrCreate will cope with either scenario, but Create will delete any existing file to replace it with a new, initially empty, one.
The FileAccess and FileShare enumerations are bitwise flags, so values can be combined with the C# bitwise OR operator, I.
There are a large number of constructors for the FileStream.
The three simplest ones work as follows:
As this code reveals, the overloads of these constructors have the effect of providing default values of FileAccess.
ReadWrite and FileShare.
Read to the third and fourth parameters.
It is also possible to create a file stream from a File Info instance in various ways:
FileInfo OpenRead () supplies a stream that gives you read-only.
access to an existing file, whereas FileInfo.
OpenWrite () gives you read-write access.
Filelnfo Open () allows you to specify the mode, access, and file share parameters explicitly.
Of Course after you have finished with a stream, you should close it:
fs. Close (. ,
Closing the stream frees up the resources associated with it and allows other applications to set up streams to the same file.
This action also flushes the buffer.
In between opening and closing the stream, you will want to read data from it and/ or write data to it.
FileStream implements a number of methods to do this.
ReadByte () is the simplest way of reading data.
It grabs 1 byte from the stream and casts the result to an int that has.a value between. 0 and 255.
If you have reached the end of the stream, it returns -1:
int NextByte = fs.ReadByte();
If you prefer to read a number of bytes at a time, you can call the Read () method, which reads a specified number of bytes into an array.
Read () returns the number of bytes actually read – if this value is zero, you know that you are at the end of the stream.
Here is an example where you read into a byte array called ByteArray:
int nBytesRead = fs.Read(ByteArray, 0, nBytes);
The second parameter to Read () is an offset, which you can use to request that the Read operation start populating the array at some element other than the first.
The third parameter is the number of bytes to read into the array.
fs.Write(ByteArray, 0, nBytes);
As with Read ( ), the:iecond parameter allows you to start writing from some point other than the beginning of the array.
Both writeByte () and write () return void.
In addition to these methods, FileStream implements various other methods and properties related to bookkeeping tasks such as determining how many bytes are in the stream, locking the stream, or flushing the buffer.
These other methods are not usually required for basic reading and writing, but if you need them, full details are in the SDK documentation.
The use of the FileStream class is illustrated by writing an example, BinarYFileReader, which reads in and displays any file, Create the project in Visual Studio 2008as a Wmdows application. It has one menu item, which brings up a standard OpenFileDialog asking what file to read in and then displays the file as binary code, As you are reading in binary files, you need to be able to display nonprintable characters You will do this by displaying each byte of the file individually, showing 16bytes on each line of a multiline text box, If the byte represents a printable ASCIIcharacter, you will display that character; otherwise, you will display the value of the byte in a hexadecimal format, In either case, you pad out the displayed text with spaces so that each byte displayed occupies four columns; this way, the bytes line up nicely under each other, What the BinaryFileReader application looks like when viewing a text file, (Because BinaryFileReader can view any file, it is quite possible to use it on text files as well as binary ones.) In this case, the application has read in a basic ASP.NETpage (. aspx).
Clearly, this format is more suited to looking at the values of individual bytes than to displaying text! Later in this chapter, when you develop an example that is specifically designed to read text files, you will be able to see what this file really says, The advantage of this example is that you can look at the contents of any file, This example will not demonstrate writing to files because you don’t want to get bogged down in the complexities of trying to translate the contents of a text box like the one into a binary stream! You see how to write to files later when you develop an example that can read or write, but only to and from text files.
Here is the code used to get these results.First, you need to make sure that you have brought in the System.
10 namespace through the use of the using statement:
using System. 10;
Next, you add a couple of fields to the main form class – one representing the file dialog and a string that gives the path of the file currently being viewed: . ./
partial class Forml : Form
private readonly OpenFileDialog
private string chosenFile;
You also need to add some standard Windows Forms code to deal with the handlers for the menu and the file dialog: .
public Forml ()
As this code demonstrates, when the user clicks OK to select a me in the file dialog, you call the DisplayFile () method, which does the work of reading in the selected File:
There is quite a lot going on in this method, so here is a breakdown. You instantiate a FileStream.
object for the selected file, which specifies that you want to open an existing file for reading.
You then work out how many bytes there are to read in and how many lines should be displayed.
The number of bytes will normally be the number of bytes in the file.
However, text boxes can display a maximum of only 65,536characters and with the chosen display format, you are displaying four characters for every byte in the file.
Therefore, you will need to cap the number of bytes shown in the text box if the selected file is longer than 65,536/4 = 16,384bytes.
If you want to display longer files in this sort of environment, you might want to look up the RichTextBox class in the System. windows.
RichTextBox is similar to a text box, but has many more advanced formatting facilities and does not have a limit on how much text it can display, TextBox is used here to keep the example simple and focused on the process of reading in files, The bulk of the method is given over to two nested for loops that construct each line of text to be displayed, You use a StringBuilder class to construct each line for performance reasons: you are appending suitable text for each byte to the string that represents each line 16 times. If on each occasion you allocate a new string and take a copy of the half-constructed line, you are not only going to be spending a lot of time allocating strings but will also be wasting a lot of memory on the heap, Notice that the definition of printable characters is anything that is a letter, digit, or punctuation, as indicated by the relevant static System.
You exclude any character with a value less than 16 from the printable list, however; this means that you will trap the carriage return (13) and line feed (10) as binary characters (a multiline text box isn’t able to display these characters properly if they occur individually within a -line), Furthermore, using the Properties window, you change the Font property for the text box to a fixed-width font.
In this case, you choose.
Courier New 9pt regular, and set the text box to have vertical
and horizontal scroll bars, Upon completion, you close the stream and set the contents of the text box to the array of strings that you have built up.