Класс Stream
Базовым классом для всех потоков является абстрактный класс Stream, располагающийся в пространстве имен System.IO. Класс обеспечивает универсальное представление всех потоков ввода-вывода.
В классе Stream определены свойства и методы, которые выполняют следующие действия:
- чтение потока;
- запись потока;
- поиск в потоке;
- закрытие потока;
- сброс потока;
- настройка тайм-аута;
- другие операции.
Операции (методы) чтения потока
Для чтения потока определены следующие методы и свойства:
- свойство CanRead — оно определяет возможность потока поддерживать чтение;
- метод Read() — метод читает последовательность байт из текущего потока;
- метод ReadByte() — метод читает один байт из текущего потока.
Свойство CanRead. Назначение. Общая форма. Пример
Свойство CanRead используется в унаследованных классах для определения того, поддерживает ли текущий поток чтение. Общая форма свойства следующая:
public abstract bool CanRead { get; }
Если свойство возвращает true, то поток поддерживает чтение.
Пример. В примере определяется, поддерживает ли файловый поток чтение.
using System;
using System.IO;
namespace nookery_ru
{
  class Program
  {
    static void Main(string[] args)
    {
      // 1. Создать поток и связать его с файлом "Myfile.txt"
      Stream stream;
      using (stream = new FileStream("Myfile.txt", FileMode.Create))
      {
        // 2. Свойство CanRead - определить, допускает ли поток чтение
        if (stream.CanRead)
          Console.WriteLine("Stream поддерживает чтение.");
        else
          Console.WriteLine("Stream не поддерживает чтение.");
        // 3. Закрыть поток
        stream.Close();
      }
    }
  }
}
Метод Read(). Пример
Абстрактный метод Read() , позволяет прочитать последовательность байт из текущего потока. Метод имеет несколько реализаций. Общая форма наиболее распространенной реализации метода:
public abstract int Read(byte[] buffer, int offset, int count)
- buffer – массив указанного размера, в который считываются данные потока;
- offset — смещение (начиная с 0) в буфере buffer, с которого начинается считывание данных из потока;
- count — максимально-возможное количество байт, которые могут быть считаны из текущего потока.
После чтения, позиция в потоке сдвигается на число прочитанных байт.
Пример. В примере, в файл записывается массив строк типа string[]. Затем этот массив строк считывается методом Read().
using System;
using System.IO;
using System.Text;
namespace nookery_ru
{
    class Program
    {
        static void Main(string[] args)
        {
            // Записать массив строк в файл
            using (FileStream fileStream = new FileStream("Text.dat", FileMode.Create, FileAccess.Write))
            {
                // Исходный массив строк
                string[] siteName = { "www", "nookery", ".", "ru" };
                byte[] buffer;
                int offset = 0;
                // Сначала записать количество строк
                buffer = BitConverter.GetBytes(siteName.Length);
                fileStream.Write(buffer, offset, buffer.Length);
                // Записать массив строк
                for (int i = 0; i < siteName.Length; i++)
                {
                    // сначала записать длину строки
                    buffer = BitConverter.GetBytes(siteName[i].Length);
                    fileStream.Write(buffer, offset, buffer.Length);
                    // затем записать саму строку
                    buffer = Encoding.Default.GetBytes(siteName[i]);
                    fileStream.Write(buffer, offset, buffer.Length);
                }
            }
            // Считать из файла массив строк
            using (FileStream fileStream = new FileStream("Text.dat", FileMode.Open, FileAccess.Read))
            {
                // Результирующий массив
                string[] siteName;
                // Дополнительные переменные
                byte[] buffer;
                // Прочитать количество строк
                buffer = new byte[sizeof(int)];
                fileStream.Read(buffer, 0, buffer.Length); // прочитать из файла байты
                int count = BitConverter.ToInt32(buffer, 0);
                int len;
                // Выделить память для массива строк
                siteName = new string[count];
                // Считать строки в цикле
                for (int i = 0; i < siteName.Length; i++)
                {
                    // Сначала считать длину строки в байтах
                    buffer = new byte[sizeof(int)];
                    fileStream.Read(buffer, 0, buffer.Length);
                    len = BitConverter.ToInt32(buffer, 0); // Получить длину строки
                    // Считать строку длиной len байт в буффер AB2
                    buffer = new byte[len]; // выделить память для буфера
                    fileStream.Read(buffer, 0, len); // считать длину в буфер
                    siteName[i] = "";
                    for (int j = 0; j < buffer.Length; j++)
                    {
                        siteName[i] = siteName[i] + (char)buffer[j];
                    }
                }
                // Вывести массив строк для контроля
                for (int i = 0; i < siteName.Length; i++)
                {
                    Console.WriteLine("{0}", siteName[i]);
                }
            }
            Console.ReadKey();
        }
    }
}

Метод ReadByte(). Пример
Виртуальный метод ReadByte() используется для чтения байта из потока. После чтения, текущая позиция чтения сдвигается на 1 байт. Если достигнут конец файла, то возвращается -1.
Общая форма метода следующая
public virtual int ReadByte()
Пример. Записываем число типа int и число типа double в файл. Затем читаем эти числа.
using System;
using System.IO;
namespace nookery_ru
{
    class Program
    {
        static void Main(string[] args)
        {
            // Запись чисел в файл
            using (FileStream fWrite = new FileStream("Myfile.txt", FileMode.Create, FileAccess.Write))
            {
                // числа, которые нужно записать
                int num1 = 45;
                double num2 = 5.55;
                // массив байт, который будет непосредственно записан в файл
                byte[] numByte1 = BitConverter.GetBytes(num1);
                byte[] numByte2 = BitConverter.GetBytes(num2);
                // записать числа - метод Write()
                fWrite.Write(numByte1, 0, numByte1.Length);
                fWrite.Write(numByte2, 0, numByte2.Length);
            }
            // Считывание строки из файла
            using (FileStream fRead = new FileStream("Myfile.txt", FileMode.Open, FileAccess.Read))
            {
                // Числа, которые будут считаны из файла
                int num1;
                double num2;
                // Массивы байт, в которые будут считаны числа из файла
                byte[] numByte1 = new byte[sizeof(int)];
                byte[] numByte2 = new byte[sizeof(double)];
                // Прочитать число типа int - использовать метод ReadByte()
                for (int i = 0; i < numByte1.Length; i++)
                    numByte1[i] = (byte)fRead.ReadByte();
                num1 = BitConverter.ToInt32(numByte1,0);
                Console.WriteLine("num1 = {0}", num1);
                // Прочитать число типа double
                for (int i = 0; i < numByte2.Length; i++)
                    numByte2[i] = (byte)fRead.ReadByte();
                num2 = BitConverter.ToDouble(numByte2,0);
                Console.WriteLine("num2 = {0}", num2);
            }
            Console.ReadKey();
        }
    }
}
