C#. Hierarchy of streams with basic storages. The FileStream class




Hierarchy of streams with basic storages. The FileStream class. The constructors of FileStream class. Instantiating FileStream. Examples. Overview of basic methods


Contents


Search other resources:

1. Hierarchy of streams with basic storages. Figure

All classes with basic storages are inherited from the Stream class. The main classes of streams with basic storages are as follows:

  • FileStream – provides access to a file. The class supports synchronous and asynchronous writing and reading of information;
  • MemoryStream – implements a stream whose basic storage is memory;
  • IsolatedStorageFileStream – implements access to a file that is located in isolated storage;
  • NetworkStream – provides the main data stream for network access. This class inherits from the FileStream class;
  • PipeStream – provides a Stream object for the main pipe that supports both anonymous and named pipes.

Figure 1 shows the classes corresponding to streams with basic stores. Classes are grouped by namespace.

C#. Streams hierarchy with basic storages

Figure 1. Streams hierarchy with basic storages

In order to use the tools for one or another class, you must first include the corresponding namespace. For example, to use the capabilities of the NetworkStream class at the beginning of the program module, you need to specify the line

using System.Net.Sockets;

   

2. FileStream class. The purpose. Instantiating the FileStream class. Enumerations FileMode, FileAccess, FileShare, FileOptions

The FileStream class is used to perform various operations on files. The class contains tools of accessing the file. Some of the methods and properties of the class are inherited from the base Stream class.

The FileStream class supports both synchronous and asynchronous file write and file read operations.

To create an instance of the FileStream class, one of the many constructors of this class must be called. Below is a list of some of them.

public FileStream(string path, System.IO.FileMode mode)
public FileStream(string path, System.IO.FileMode mode, System.IO.FileAccess access)
public FileStream(string path, System.IO.FileMode mode, System.IO.FileAccess access, System.IO.FileShare share)
public FileStream(string path, System.IO.FileMode mode, System.IO.FileAccess access, System.IO.FileShare share, int bufferSize)
public FileStream(string path, System.IO.FileMode mode, System.IO.FileAccess access, System.IO.FileShare share, int bufferSize, bool useAsync)
public FileStream(string path, System.IO.FileMode mode, System.IO.FileAccess access, System.IO.FileShare share, int bufferSize, System.IO.FileOptions options)

here

  • path – path to a file on a disk or other storage medium;
  • mode – one of the values of the FileMode enumeration, which determines the file access mode (Open, Append, Create);
  • access — specifies access to the file based on the set of constants of the FileAccess enumeration;
  • share – defines the type of access control to a file from other objects based on a set of constants from the FileShare enumeration;
  • bufferSize is a positive System.Int32 value that defines the size of the buffer in bytes. By default, bufferSize = 4096 bytes;
  • useAsync – determines whether synchronous or asynchronous I/O will occur. It should be noted that not all operating systems support asynchronous I/O. If useAsync = true, then asynchronous I/O is provided;
  • options – specifies additional configuration options when creating an object of the FileStream type. These options have fixed values and are represented by the FileOptions enumeration.

In the above constructors, the file open mode is set from the set of values of the FileMode enumeration:

  • Append – the mode of opening a file to add. This mode can be used in combination with the FileAccess.Write access mode. If the file exists, the file is opened and the file read pointer is rewound to the end of the file. If the file does not exist, a new file is created;
  • Create – the mode of creating a new file. This mode is used in combination with FileAccess.Write access. If the file does not exist, then a new file is created at the specified path. If the file exists, it will be overwritten;
  • CreateNew – mode, instructs the operating system to create a new file. This mode is used in combination with the FileAccess.Write access modifier. The difference between this mode and FileMode.Create is that if the file already exists, then a System.IO.IOException will be thrown;
  • Open – the mode of opening the existing file. Access to a file (read, write, or read/write) is determined by a value from the FileAccess enumeration (see below). If the file does not exist, then a System.IO.FileNotFoundException will be thrown;
  • OpenOrCreate – file open mode. If the file does not exist, a new file is created. The file can be opened with any access (FileAccess.Read, FileAccess.Write, FileAccess.ReadWrite);
  • Truncate – sets the mode of opening an existing file with its truncation. When the file is open, it should be truncated to zero size. This mode is combined with access to the FileAccess.Write file. If you try to read a file in Truncate mode, a System.ArgumentException will be thrown.

The FileAccess enumeration defines access to a file based on one of the following constants:

  • Read – the file is readable;
  • ReadWrite – the file is available for writing and reading;
  • Write – the file is available for writing.

The FileShare enumeration defines access control for other objects of type FileStream and can have the following values:

  • Delete – gives permission to further delete the file;
  • Inheritable – indicates that child processes can inherit the file handler;
  • None – denies access to the current file. Any request to open the current file will be closed;
  • Read – allows further opening of the file for reading. If this value is not specified, then any attempt to open the file for reading from another process will fail until the file is closed;
  • ReadWrite – gives permission to further open the file for reading or writing. If this flag is not specified, then any attempt to open a file from the current or another process will fail;
  • Write – gives permission to further open the file for writing. If you do not specify this value, then any attempt to open the file for writing from another process (stream) will fail until the file is closed.

The FileOptions enumeration implements additional features (options) that determine the purpose of an open file:

  • Asynchronous – indicates that the file can be used for asynchronous reading and writing;
  • DeleteOnClose – indicates that the file will be deleted after it is no longer used;
  • Encrypted – indicates that the file is encrypted and can only be decrypted using the same user account used for encryption;
  • None – indicates that no additional options are applied for the created object of type FileStream;
  • RandomAccess — Indicates that the file is being accessed randomly. This hint gives the system a hint to optimize file caching;
  • SequentialScan – indicates that the file is being read sequentially from beginning to end. This hint can be used as a hint to the system to optimize file caching. This may provide some performance improvement;
  • WriteThrough — instructing the system to write through any intermediate cache and go directly to disk.

   

3. Examples showing how to create instances of the FileStream type for various use cases
3.1. File creation. The simplest case. Example

To create a new file, you need to set the file creation mode to FileMode.Create. The peculiarity of this mode is that if the file is present and it is hidden, then an UnauthorizedAccessException will be thrown. Therefore, to create a file, you can write something like the following code:

// Create a new file named "myfile.txt".
// If the file already exists, it will be overwritten.
try
{
  FileStream fs = new FileStream("myfile.txt", FileMode.Create);

  // Using file
  // ...

  // Close file after use
  fs.Close();
}
catch (UnauthorizedAccessException e)
{
  // Processing if the file is present and it is hidden
  Console.WriteLine("Error: " + e.Message);
}

File creation cannot be with FileAccess.Read access mode. If you write code like this:

...
FileStream fs = new FileStream("myfile4.txt", FileMode.Create, FileAccess.Read);
...

then after running, the program will throw a System.ArgumentException.

   

3.2. Opening an already existing file for reading. The simplest case. Example

If the file is already on the disk, then to read information from it without modifying it, you need to use the FileMode.Open mode and FileAccess.Read access. If the file is not on disk, then a FileNotFoundException will be thrown. Therefore, you need to catch this exception.

// Opening a file for reading
try
{
  FileStream fOpen = new FileStream("myfile5.txt", FileMode.Open, FileAccess.Read);

  // Read data from file
  // ...

  // When finished, close the file
  fOpen.Close();
}
catch (FileNotFoundException e)
{
  // Handle error if file not found
  Console.WriteLine("Error: " + e.Message);
}

   

3.3. Examples of processing (writing/reading) a file with the specified type of access. FileShare enumeration

Controlling the accessibility of the file being processed to other instances is defined in the constructor of the FileStream class. The constructor takes as a parameter a value from the FileShare enumeration, which determines how the file is shared from different FileStream instances.

   

3.3.1. Reading data from a file by different (parallel) objects

If you want the processed file to be read by another object, then you need to specify FileShare.Read as shown below

// Reading from the same file with different FileStream objects
try
{
  // Allow another object to read data from the file "myfile.txt"
  FileStream fs = new FileStream("myfile.txt", FileMode.Open, FileAccess.Read, FileShare.Read);

  // Create another object that will read from the same file
  FileStream fs2 = new FileStream("myfile.txt", FileMode.Open, FileAccess.Read);

  // Using the file "myfile.txt" by two objects fs and fs2
  // ...

  // Close files after using
  fs.Close();
  fs2.Close();
}
catch (UnauthorizedAccessException e)
{
  // Processing if the file is already present and it is hidden
  Console.WriteLine("Error: " + e.Message);
}
catch (FileNotFoundException e)
{
  // Обработка, если файл не найден
  Console.WriteLine("Error: " + e.Message);
}

   

3.3.2. Writing data to a file from various objects. Example

In order to simultaneously write to a file from various objects, you need to specify FileShare.Write when creating a file object of the FileStream type according to the example below

...

// Writing to the file "myfile.txt" by two different objects
try
{
  // Indicate that writing to the file "myfile.txt" will be multiple objects - FileShare.Write
  FileStream fw1 = new FileStream("myfile.txt", FileMode.Open, FileAccess.Write, FileShare.Write);

  // Create another object that will write to the same file,
  // be sure to specify FileShare.Write

  FileStream fw2 = new FileStream("myfile.txt", FileMode.Open, FileAccess.Write, FileShare.Write);

  // Using the file "myfile.txt" by two objects - writing from two different instances
  // ...

  // Close file objects after use
  fw1.Close();
  fw2.Close();
}
catch (FileNotFoundException e)
{
  // Processing if file not found
  Console.WriteLine("Error: " + e.Message);
}

   

3.3.3. An example of writing two numbers to a file and reading them with different objects

This example demonstrates:

  • writing double and int numbers from two different instances of the FileStream class to a file. The offset is taken into account when writing;
  • reading from a file numbers of type double and int from two different instances of the FileStream class. As with writing, offset is taken into account;
  • capabilities of the BitConverter class for converting various types to byte[] array and vice versa;
  • using and combining the Write() and Seek() methods to write data of various types;
  • using the ReadByte() method to form an array of type byte[].
using System;
using System.IO;
using System.Text;

namespace ConsoleApp10
{
  class Program
  {
    static void Main(string[] args)
    {
      // Writing to the file "myfile.txt" by two different objects
      try
      {
        // Indicate that writing to the file "myfile.txt" will be multiple objects - FileShare.Write
        FileStream fw1 = new FileStream("myfile.txt", FileMode.Open, FileAccess.Write, FileShare.Write);

        // Create another object that will write to the same file,
        // be sure to specify FileShare.Write
        FileStream fw2 = new FileStream("myfile.txt", FileMode.Open, FileAccess.Write, FileShare.Write);

        // Using the file "myfile.txt" by two objects - writing from two different instances
        double d = 288.36;
        int i = 1230;

        // Converting to bytes[] arrays
        byte[] AD = BitConverter.GetBytes(d);
        byte[] AI = BitConverter.GetBytes(i);

        // Write a double d from the fs object to a file
        fw1.Write(AD, 0, AD.Length);

        // Write to the file the number i of the int type from the fs2 object
        fw2.Seek(0, SeekOrigin.End); // don't forget for scrolling to the end of the file
        fw2.Write(AI, 0, AI.Length); // write integer

        // Close files after using
        fw1.Close();
        fw2.Close();
      }
      catch (UnauthorizedAccessException e)
      {
        // Processing if the file is present and hidden
        Console.WriteLine("Error: " + e.Message);
      }
      catch (FileNotFoundException e)
      {
        // Processing if file not found
        Console.WriteLine("Error: " + e.Message);
      }

      // Reading from data file by different objects
      try
      {
        // The first object - will read a double
        FileStream fr1 = new FileStream("myfile.txt", FileMode.Open, FileAccess.Read, FileShare.Read);

        // Second object - will read an int number from the same file as fr1
        FileStream fr2 = new FileStream("myfile.txt", FileMode.Open, FileAccess.Read, FileShare.Read);

        // Read a double from the fr1 object
        byte[] AD = new byte[sizeof(double)]; // allocate memory for double type
        double d; // result

        // Read byte - method ReadByte (),
        // instead of a loop, you can also use fr1.Read (AD, 0, AD.Length)
        for (int i = 0; i < AD.Length; i++)
          AD[i] = (byte)fr1.ReadByte();
        d = BitConverter.ToDouble(AD);
        Console.WriteLine("d = {0}", d);

        // Read an int number from another fr2 object
        int t;
        byte[] AI = new byte[sizeof(int)];

        // Read into array AI, take into account the offset,
        // fast forward by the size of the double type
        fr1.Seek(sizeof(double), SeekOrigin.Begin);

        // consider a number of type int as an array byte[]
        fr1.Read(AI, 0, AI.Length);

        // convert byte[] => int
        t = BitConverter.ToInt32(AI);
        Console.WriteLine("t = {0}", t);

        fr1.Close();
        fr2.Close();
      }
      catch (FileNotFoundException e)
      {
        // Handle error if file not found
        Console.WriteLine("Error: " + e.Message);
      }
    }
  }
}

   

3.3.4. An example of alternately writing and reading data from one file. Demonstration of FileShare.ReadWrite access

The example demonstrates the simultaneous writing and reading of an integer from a shared open file. It is assumed that the file has been previously created.

using System;
using System.IO;

namespace ConsoleApp10
{
  class Program
  {
    static void Main(string[] args)
    {
      // Accessing one file from two different instances:
      // - instance fWrite - writes a number to the file;
      // - fRead instance - reads the written number from the file and displays it on the screen.
      try
      {
        // Indicate that writing to the file "myfile.dat" will be multiple objects - FileShare.ReadWrite
        FileStream fWrite = new FileStream("myfile.dat", FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite);

        // Create another object that will read from the same file,
        // be sure to specify FileShare.ReadWrite
        FileStream fRead = new FileStream("myfile.dat", FileMode.Open, FileAccess.Read, FileShare.ReadWrite);

        // Using the file "myfile.dat" by two objects - fWrite and fRead
         
        // The cycle of writing numbers 5, 10, 15 to a file by an object and reading them by another instance
        byte[] A; // additional array
        int num; // число, которое нужно написать
        int offset; // the offset in the file
        A = new byte[sizeof(int)]; // buffer for one number of type int
        byte[] A2;

        for (int i = 0; i < 3; i++)
        {
          // 1. Form number
          num = (i + 1) * 5;

          // 2. Write number to file "myfile.dat"
          // 2.1. Converting num => to array byte[]
          A = BitConverter.GetBytes(num);

          // 2.2. Calculate the offset to write to the file
          offset = 0 + i * sizeof(int);

          // 2.3. Rewind the current write position by offset
          fWrite.Seek(offset, SeekOrigin.Begin);

          // 2.4. Write num to the file
          fWrite.Write(A, 0, A.Length);

          // 3. Immediately read the written number from the file
          // 3.1. Allocate memory for a buffer of type byte[], use an additional variable A
          A2 = new byte[sizeof(int)];

          // 3.2. Calculate the offset
          offset = 0 + i * sizeof(int);

          // 3.3. Rewind the current read position by offset bytes
          fRead.Seek(offset, SeekOrigin.Begin);

          // 3.4. Read number into buffer A2
          fRead.Read(A2, 0, A2.Length);

          // 3.5. Convert byte[] => int
          int num2 = BitConverter.ToInt32(A2);

          // 3.6. Display num2
          Console.WriteLine("{0} ", num2);
        }

        // Close files after using
        fWrite.Close();
        fRead.Close();
      }
      catch (FileNotFoundException e)
      {
        // Processing if file not found
        Console.WriteLine("Error: " + e.Message);
      }
    }
  }
}

The result of the program

5
10
15

   


Related topics