C#. Класс BinaryReader. Работа с файлами




Класс BinaryReader. Работа с файлами в двоичном формате

Перед изучением данной темы рекомендуется ознакомиться со следующими темами:


Содержание


Поиск на других ресурсах:

1. Классы BinaryReader и BinaryWriter. Назначение. Общая информация

Классы BinaryReader и BinaryWriter предназначены соответственно для чтения и записи данных в двоичном формате.

Для чтения данных примитивных типов и строк из потока используется класс BinaryReader. При чтении можно указать необходимую кодировку. По умолчанию установлена кодировку UTF-8.

Класс BinaryWriter используется для записи в поток стандартных типов данных и строк в двоичном формате. Существует возможность указания кодировки (по умолчанию UTF-8).

Классы реализованы в пространстве имен System.IO. Для того, чтобы использовать возможности классов BinaryReader, BinaryWriter нужно подключить System.IO

using System.IO;

 

2. Взаимодействие класса BinaryReader с потоками опорных хранилищ. Использование класса FileStream

Как известно, классы BinaryReader и BinaryWriter относятся к адаптерам потоков. Непосредственно взаимодействовать с различными видами хранилищ классы не могут. Для того, чтобы подойти к файловому, сетевому или иному виду хранилища нужно:

  • создать экземпляр соответствующего класса как потока. Это может быть экземпляр одного из четырех классов FileStream, IsolatedStorageStream, MemoryStream или NetworkStream;
  • связать созданный экземпляр с экземпляром класса BinaryReader или BinaryWriter.

Например. Для того, чтобы прочитать информацию из файла или записать ее в файл, нужно создать экземпляр потока FileStream (рисунок 1).

C#. Взаимодействие класса BinaryReader с файлом с помощью класса FileStream

Рисунок 1. Взаимодействие класса BinaryReader с файлом с помощью класса FileStream

 

3. Конструкторы класса BinaryReader. Создание экземпляра

Класс BinaryReader имеет несколько конструкторов, наиболее используемые из которых следующие:

public BinaryReader(System.IO.Stream input)
public BinaryReader(System.IO.Stream input, System.Text.Encoding encoding)

здесь

  • input – ссылка на абстрактный базовый класс Stream;
  • encoding – система кодировки (Unicode, UTF32, UTF8 и другая). По умолчанию устанавливается система кодировки UTF8.

Пример. В примере продемонстрировано создание экземпляра класса BinaryReader с кодировкой по умолчанию.

...

// Создать поток, который связан с файлом "abc.bin"
using (FileStream fs = new FileStream("abc.bin",
       FileMode.Open))
{
  // Связать экземпляр BinaryReader с потоком fs
  using (BinaryReader br = new BinaryReader(fs, Encoding.Default))
  {
    ...
  }
}

 

4. Класс BinaryReader. Обзор основных методов

Основные методы, читающие данные в классе — это методы, которые начинаются с префикса Read. Далее приведен перечень этих методов.

4.1. Методы типа Read…() для чтения данных примитивных типов (int, bool, double, …)

Для считывания данных примитивных (стандартных) типов (int, double, char и других) в двоичном формате используется ряд методов. Предварительно эти данные должны быть записаны методом Write().

Ниже дан перечень этих методов.

 

4.1.1. Метод ReadBoolean()

Общая форма метода

public virtual bool ReadBoolean()

Метод считывает значение типа bool из текущего потока и сдвигает текущую позицию на один байт.

Пример. Считывание из файла значения логического типа bool. Фрагмент кода предполагает, что это значение предварительно было записано методом Write().

...

FileStream fs = new FileStream("file3.bin", FileMode.Open);
BinaryReader br = new BinaryReader(fs, Encoding.Default);

...

// Считать значение типа bool
bool b;
b = br.ReadBoolean();

...

 

4.1.2. Методы ReadByte() и ReadBytes()

Метод ReadByte() считывает из потока один байт. Метод ReadBytes() считывает из потока несколько байт. Общая форма методов

public virtual byte ReadByte()
public virtual byte[] ReadBytes(int count)

здесь count – количество считываемых байт.

Пример. Приводится пример считывания данных методами ReadByte() и ReadBytes().

...

FileStream fs = new FileStream("file.dat", FileMode.Open);
BinaryReader br = new BinaryReader(fs, Encoding.Default);

...

// Считать один байт из файла "file.dat"
byte b = br.ReadByte();

// Считать 30 байт из файла "file.dat" в массив AB
byte[] AB = br.ReadBytes(30);

...

 

4.1.3. Методы ReadChar() и ReadChars(int)

Методы используются для считывания одиночного символа типа char или нескольких символов типа char. Общая форма методов следующая:

public virtual char ReadChar()
public virtual char[] ReadChars(int count)

здесь count – количество символов, которые нужно прочитать из потока.

Пример.

...

FileStream fs = new FileStream("file.dat", FileMode.Open);
BinaryReader br = new BinaryReader(fs, Encoding.Default);

...

// Считать один символ
char c = br.ReadChar();

// Считать 10 символов в массив AC
char[] AC = br.ReadChars(10);

...

 

4.1.4. Методы чтения данных с плавающей запятой ReadDecimal(), ReadDouble(), ReadSingle()

Для чтения данных с алавающей запятой используются методы ReadDecimal(), ReadDouble(), ReadSingle(), которые считывают данные типов decimal, double и float соответственно. Общая форма методов следующая:

public virtual decimal ReadDecimal()
public virtual double ReadDouble()
public virtual float ReadSingle()

Пример. В примере считывается массив вещественных чисел из файла.

...

FileStream fs = new FileStream("file.bin", FileMode.Open);
BinaryReader br = new BinaryReader(fs, Encoding.Default);

...

float[] AF2;

// Прочитать количество записаных чисел
int count = br.ReadInt32();

// Выделить память для массива
AF2 = new float[count];

// Цикл считывания элементов массива
for (int i = 0; i < count; i++)
  AF2[i] = (float)br.ReadSingle(); // метод ReadSingle

...

 

4.1.5. Методы ReadInt16(), ReadInt32(), ReadInt64() чтения данных типа int

Для чтения данных типа int используются следующие методы:

  • ReadInt16() — считывает 2-байтовое знаковое целое число из текущего потока;
  • ReadInt32() — считывает 4-байтовое знаковое целое число из потока;
  • ReadInt64() — считывает 8-байтовое знаковое целое число из потока.

Общая форма методов следующая

public virtual short ReadInt16()
public virtual int ReadInt32()
public virtual long ReadInt64()

Пример.

...

FileStream fs = new FileStream("file.bin", FileMode.Open);
BinaryReader br = new BinaryReader(fs, Encoding.Default);

...

// Прочитать данные типов short, int, long
short s = br.ReadInt16();
int d = br.ReadInt32();
long l = br.ReadInt64();

...

 

4.1.6. Метод ReadSByte(). Чтение данных типа sbyte

Метод ReadSByte() считывает данные типа sbyte. Общая форма метода:

public virtual sbyte ReadSByte()

Пример.

...

FileStream fs = new FileStream("file.bin", FileMode.Open);
BinaryReader br = new BinaryReader(fs, Encoding.Default);

...

// Считать данные типа sbyte
sbyte sb = br.ReadSByte();

...

 

4.1.7. Метод ReadString(). Чтение строки типа string

Для чтения одной строки из текущего потока используется метод ReadString(), который имеет следующую общую форму:

public virtual string ReadString()

Пример.

...

FileStream fs = new FileStream("file.bin", FileMode.Open);
BinaryReader br = new BinaryReader(fs, Encoding.Default);

...

// Считать данные типа string
string s = br.ReadString();

...

 

4.1.8. Методы считывания данных беззнакового целого типа

Для считывания беззнаковых целых типов используются методы ReadUint16(), ReadUint32(), ReadUint64(). Общая форма методов

public virtual ushort ReadUInt16()
public virtual uint ReadUInt32()
public virtual ulong ReadUInt64()

Пример.

using (FileStream fs = new FileStream("file3.bin",
       FileMode.Create))
{
  using (BinaryWriter bw = new BinaryWriter(fs, Encoding.Default))
  {

    ...

    // Считать данные типов ushort, uint, ulong
    ushort us = br.ReadUInt16();
    uint ui = br.ReadUInt32();
    ulong ul = br.ReadUInt64();

    ...
  }
}

 

4.2. Метод Read()

Метод Read() имеет несколько перегруженных реализаций. Ниже приведена общая форма наиболее употребляемых реализаций метода. Первая реализация метода не содержит параметров

public virtual int Read()

При такой реализации считываются символы из базового потока и перемещается текущая позиция потока вперед в соответствии с используемым кодированием. Метод возвращает следующий символ из потока ввода.

Следующие реализации

public virtual int Read(byte[] buffer, int index, int count)
public virtual int Read(char[] buffer, int index, int count)

считывают соответственно определенное число байт или символов из потока, начиная с определенного потока в массиве байт.

Пример.

В примере демонстрируется использование метода Read(), который считывает массив байт типа byte[]. Сначала в файл записывается массив типа double[]. Затем этот массив считывается методом Read(byte[], int, int).

Пример также демонстрирует возможности класса BitConverter, который предназначен для преобразования различных типов в тип byte[] и, наоборот. Демонстрируется конвертирование чисел массива double[] в массив byte[].

Текст программы следующий.

using System;
using System.IO;
using System.Text;

namespace ConsoleApp10
{
  class Program
  {
    static void Main(string[] args)
    {
      // Записать в файл file3.bin массив чисел типа double[]
      // 1. Запись чисел
      using (FileStream fs = new FileStream("file3.bin",
             FileMode.Create))
      {
        using (BinaryWriter bw = new BinaryWriter(fs, Encoding.Default))
        {
          // 1.1. Записываемые данные
          double[] AD = { 2.8, 3.3, 1.4 };

          // 1.2. Вспомогательный массив
          byte[] B;

          // 1.3. Записать количество чисел
          bw.Write(AD.Length);

          // 1.4. Цикл записи чисел в файл
          for (int i = 0; i < AD.Length; i++)
          {
            // Конвертировать double => byte[]
            B = BitConverter.GetBytes(AD[i]);

            // Записать массив byte[] в файл
            bw.Write(B, 0, B.Length);
          }
        }
      }

      // 2. Считывание из файла массива чисел типа double[]
      using (FileStream fs = new FileStream("file3.bin", FileMode.Open))
      {
        using (BinaryReader br = new BinaryReader(fs, Encoding.Default))
        {
          // 2.1. Вспомогательные переменные
          double[] AD2; // Массив-результат
          byte[] B2 = new byte[sizeof(double)]; // выделить память для буфера

          // 2.2. Считать количество чисел, записанных в файле
          int count = br.ReadInt32();
          AD2 = new double[count]; // выделить память

          // 2.3. Считать числа в массив AD2
          for (int i = 0; i < AD2.Length; i++)
          {
            br.Read(B2, 0, sizeof(double));
            AD2[i] = BitConverter.ToDouble(B2, 0);
          }

          // 2.4. Вывести массив AD2 для контроля
          Console.Write("AD2 = { ");
          for (int i = 0; i < AD2.Length; i++)
            Console.Write(AD2[i] + " ");
          Console.WriteLine("}");
        }
      }
    }
  }
}

Результат работы программы

AD2 = { 2.8 3.3 1.4 }

 

4.3. Метод PeekChar()

Метод PeekChar() получает следующий имеющийся символ без прироста позиции байта или символа

public virtual int PeekChar()

Если невозможно прочитать символ (например, конец файла), то метод возвращает -1.

Пример. В примере в файл записывается строка, затем эта строка считывается посимвольно. Для определения того, можно ли прочитать символ, используется метод PeekChar().

using System;
using System.IO;
using System.Text;

namespace ConsoleApp10
{
  class Program
  {
    static void Main(string[] args)
    {
      // Записать в файл file3.bin массив чисел типа float[]
      // 1. Запись чисел
      using (FileStream fs = new FileStream("file3.bin",
              FileMode.Create))
      {
        using (BinaryWriter bw = new BinaryWriter(fs, Encoding.Default))
        {
          // 1.1. Записываемые данные
          string s = "Hello world!";

          // 1.2. Записать строку посимвольно
          char[] cc = s.ToCharArray();

          for (int i = 0; i < s.Length; i++)
          {
            bw.Write(s[i]);
          }
        }
      }

      // 2. Считывание из файла массива чисел типа float
      using (FileStream fs = new FileStream("file3.bin", FileMode.Open))
      {
        using (BinaryReader br = new BinaryReader(fs, Encoding.Default))
        {
          // Считать строку посимвольно
          char c;

          // Чтение посимвольно, пока можно прочитать
          while (br.PeekChar()!=-1)
          {
            c = br.ReadChar();
            Console.Write(c);
          }
        }
      }
    }
  }
}

 


Связанные темы