You can use the FileStream class for reading from or writing to a binary file.
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.
Enumeration | Description |
---|---|
FileMode – how to open or create this file? | |
FileMode.Append | Opens 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.CreateNew | Creates a new file if no such file exists – if the file already exists, an IOException is thrown |
FileMode.Create | Creates 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.Open | Opens an existing file – if file does not exist, throws a FileNotFoundException |
FileMode.OpenOrCreate | Opens 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.Truncate | Opens an existing file, and immediately truncates its contents |
FileAccess – how the file can be accessed by the file stream | |
FileAccess.Read | Opens a file for reading only |
FileAccess.ReadWrite | Opens a file for reading and writing |
FileAccess.Write | Opens a file for writing only |
FileShare – how the file can be shared by other processes | |
FileShare.None | File is not to be shared by another process until it is closed |
FileShare.Read | File can be opened by another process for reading only |
FileShare.ReadWrite | File can be opened by another process for reading and writing |
FileShare.Write | File 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.
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 (68→D, 101→e, 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.
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 (65→A, 66→B, 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 (67→C).
Good developers close their files after use:
fs.Close();
You have already seen it in previous code examples.
3.144.97.216