18.3. Reading from or writing to a binary file

You can use the FileStream class for reading from or writing to a binary file.

18.3.1. Creating a FileStream object

You create an instance of a FileStream object by passing in the path to the file you want to read. The FileStream class has several overloaded constructors which you can use to specify the following options:

  • file mode

  • file access

  • file share.

Table 18.5 describes these options.

Table 18.5. The available file mode, access, and share options that can be used when instantiating a FileStream
EnumerationDescription
FileMode – how to open or create this file?
FileMode.AppendOpens a file, if it exists, for appending. Moves the file pointer to the end of the existing file, so that the original data will not be overwritten – can only be used if file access has been set to FileAccess.Write
FileMode.CreateNewCreates a new file if no such file exists – if the file already exists, an IOException is thrown
FileMode.CreateCreates a new file regardless of whether it currently exists – overwrites, the file if it exists (i.e. delete existing file if any) without throwing an exception
FileMode.OpenOpens an existing file – if file does not exist, throws a FileNotFoundException
FileMode.OpenOrCreateOpens an existing file if there is one, or creates a new file if one does not currently exist – if writing to an existing file, writing starts from the first byte of the file and will overwrite existing bytes, but leaving the remaining bytes unchanged
FileMode.TruncateOpens an existing file, and immediately truncates its contents
FileAccess – how the file can be accessed by the file stream
FileAccess.ReadOpens a file for reading only
FileAccess.ReadWriteOpens a file for reading and writing
FileAccess.WriteOpens a file for writing only
FileShare – how the file can be shared by other processes
FileShare.NoneFile is not to be shared by another process until it is closed
FileShare.ReadFile can be opened by another process for reading only
FileShare.ReadWriteFile can be opened by another process for reading and writing
FileShare.WriteFile can be opened by another process for writing only

There are three useful constructors which you can use for FileStream.

  • public FileStream (string path, int fileMode);

  • public FileStream (string path, int fileMode, int fileAccess);

  • public FileStream (string path, int fileMode, int fileAccess, int fileShare);

For example, the following statement:

FileStream fs = new
  FileStream("c:\expt\loveletter.dat",
              FileMode.OpenOrCreate);

creates a new file under the specified name if it does not exist, or opens it if it already exists. The default file access is ReadWrite, and the default file share is Read.

The following statement:

FileStream fs = new
  FileStream("c:\expt\loveletter.dat",
             FileMode.Create,
             FileAccess.Write,
             FileShare.None);

creates a new file for writing only. This file cannot be shared by another process until it has been closed. If the file already exists, it will be overwritten.

18.3.2. Reading from a FileStream object

With the FileStream object created, you can use either of the following methods for reading data from the stream:

  • public override int ReadByte()

  • public override int Read(in byte[] array, int offset, int count)

ReadByte() reads a single byte from the stream, casts it into an int, and returns an int. It returns -1 when the end of the stream has been reached.

The following statements open a stream and read in data one byte at a time.

 1:  using System;
 2:  using System.IO;
 3:
 4:  public class TestClass{
 5:
 6:    public static void Main(){
 7:      FileStream fs = new FileStream
 8:        ("c:\expt\loveletter.txt",
 9:          FileMode.Open,
10:          FileAccess.Read);
11:
12:      int i=0;
13:      while (i>-1){
14:        i = fs.ReadByte();
15:        Console.Write(i+",");
16:      }
17:      fs.Close();
18:    }
19:  }

Output: [5]

[5] The output shows the contents of the loveletter.txt file in my c:expt folder. Of course, the output will differ if you put different stuff into yours!

c:expt>test
68,101,97,114,32,74,117,108,105,101,116,44,13,10,73,32,121,101,97,114,110,32,102,111,114
,32,117,33,13,10,89,111,117,114,32,82,111,109,101,111,13,10,-1,

A FileNotFoundException is thrown if my loveletter.txt doesn't already exist in c:expt. If there is no expt directory in c:, a DirectoryNotFoundException is thrown instead. The integral equivalents of the characters are shown (68D, 101e, etc.). Of course, you can also explicitly cast the ints into char values if you are reading a text file. [6]

[6] If you are reading/writing a text file, use StreamReader and StreamWriter instead of FileStream. These classes have more convenient methods specially tailored for interacting with text files.

Read()gives you more control than ReadByte(). Read() takes in:

  • a byte array which will be populated;

  • a specified number of bytes from the stream into a byte array; and

  • the array's index to start the population.

It returns the number of bytes actually read (this may differ from the number of bytes specified to be read, and is zero if the end of stream has been reached).

Let's look at an example. I have replaced the Main method of the code above with the following lines:

12:  byte []byteArray = new byte[50];
13:  int noBytesRead = fs.Read(byteArray,5,20);
14:
15:  Console.WriteLine("noBytesRead: "+noBytesRead);
16:  // display array contents
17:  for (int i=0; i<50; i++)
18:    Console.Write(byteArray[i] + ",");

Output:

c:expt>test
noBytesRead: 20
0,0,0,0,0,68,101,97,114,32,74,117,108,105,101,116,44,13,10,73,
32,121,101,97,114,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,

Line 13 instructs that the first 20 bytes are to be read from loveletter.txt into byteArray's sixth slot (byteArray[5]). The next time a Read or ReadByte is called on fs, reading carries on from the 21 st byte in the file.

18.3.3. Writing to a FileStream object

With the FileStream object created, use either of the following methods to write data to the stream:

  • public override void WriteByte(byte value)

  • public override void Write(byte[] array, int offset, int count)

WriteByte simply takes in a byte and writes it to the FileStream object.

 1:  using System;
 2:  using System.I/O;
 3:
 4:  public class TestClass{
 5:
 6:    public static void Main(){
 7:      FileStream fs = new FileStream
 8:        ("c:\expt\alphabet.txt",
 9:          FileMode.Create,
10:          FileAccess.Write);
11:
12:      for (byte i=65; i<91; i++)
13:        fs.WriteByte(i);
14:
15:      fs.Close();
16:    }
17:  }

Contents of alphabet.txt:

c:expt>type alphabet.txt
ABCDEFGHIJKLMNOPQRSTUVWXYZ

Lines 12 – 13 loops through 26 times and writes the alphabet (65A, 66B, etc.) to alphabet.txt.

Write() takes in:

  • a byte array which contains the bytes to write in;

  • the array offset (which element in the array do we start with?); and

  • the count (the number of bytes to write).

Lines 12+ above have been modified to use Write instead of WriteByte:

12:      byte []array = {65,66,67,68,69,70,71,72,73,74};
13:      fs.Write (array, 2, 5);
14:
15:      fs.Close();
16:    }
17:  }

Contents of alphabet.txt:

c:expt>type alphabet.txt
CDEFG

Line 13 says to take five bytes from array starting from array[2], and write these into the FileStream object. array[2] is 67 (67C).

18.3.3. Closing a FileStream object

Good developers close their files after use:

fs.Close();

You have already seen it in previous code examples.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.97.216