C#. Приклади застосування класу FileStream без використання додаткових потоків




Приклади застосування класу FileStream без використання додаткових потоків (декораторів, адаптерів)

Перед вивченням даної теми рекомендується ознайомитись з наступними темами:

Клас FileStream може бути застосований автономно без використання додаткових потоків адаптерів чи декораторів. Для цього у класі є всі необхідні засоби (методи). Основні методи клас успадковує від базового класу Stream.


Зміст


Пошук на інших ресурсах:

1. Приклад читання/запису числа типу double у файл. Використання FileStream

У прикладі продемонстровано використання засобів класу FileStream та базового класу Stream для запису/читання числа типу double у файл.

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

namespace ConsoleApp10
{
  class Program
  {
    static void Main(string[] args)
    {

      // Приклад запису/читання числа типу double у файл "file1.bin".
      // Методи Read(), Write() класу FileStream

      // 1. Запис у файл числа
      // 1.1. Створити файл з іменем "file1.bin" для запису
      using (FileStream fs = new FileStream("file1.bin",
FileMode.Create, FileAccess.Write))
      {
        // 1.2. Задане число
        double x = 2.55;

        // 1.3. Конвертувати x в масив byte[]
        byte[] bt = Encoding.Default.GetBytes(x.ToString());

        // 1.4. Запис числа x в файл
        fs.Write(bt, 0, bt.Length);
      }

      // 2. Зчитати число з файлу - метод Read()
      using (FileStream fs2 = new FileStream("file1.bin", FileMode.Open, FileAccess.Read))
      {
        // 2.1. Оголосити масив-буфер, в який буде зчитано дані з файлу
        byte[] bt2 = new byte[10]; // 10 байт - достатньо для числа типу double

        // 2.2. Зчитати число з файлу в масив bt2
        fs2.Read(bt2, 0, bt2.Length);

        // 2.3. Конвертувати bt2 в тип string - в рядок st
        string st = Encoding.Default.GetString(bt2);

        // 2.4. Конвертувати st в x2 типу double
        double x2 = Convert.ToDouble(st);

        // 2.5. Вивести x2 для контролю
        Console.WriteLine("x2 = {0}", x2); // x2 = 2.55
      }
    }
  }
}

 

2. Приклад запису/читання масиву чисел типу int[]

У прикладі продемонстровано запис масиву типу int[] в файл та його читання. У програмному коді використовуються методи Read(), Write() базового класу Stream. Оскільки методи Read(), Write() вимагають представлення даних у вигляді масиву байт типу byte[], то для виконання операцій конвертування використовуються можливості класу BitConverter.

using System;
using System.IO;

namespace ConsoleApp10
{
  class Program
  {
    static void Main(string[] args)
    {
      // Запис масиву чисел типу int[] у файл "array.bin"
      using (FileStream fs = new FileStream("array.bin", FileMode.Create, FileAccess.Write))
      {
        // Масив, який потрібно записати у файл
        int[] AI = { 1, 3, 8, 4, 2, 6 };

        // Допоміжний буфер типу byte[]
        byte[] AB;

        // Спочатку потрібно записати кількість чисел у масиві,
        // для цього можна скористатись класом BitConverter.
        // Представити число AI.Length як послідовність байт
        AB = BitConverter.GetBytes(AI.Length);
        fs.Write(AB, 0, AB.Length);

        // Цикл поелементного запису чисел масиву
        for (int i = 0; i < AI.Length; i++)
        {
          AB = BitConverter.GetBytes(AI[i]);
          fs.Write(AB, 0, AB.Length);
        }
      }

      // Читання масиву чисел типу int[] з файлу array.bin
      using (FileStream fs = new FileStream("array.bin", FileMode.Open, FileAccess.Read))
      {
        int[] AI2; // масив - результат
        byte[] AB2; // допоміжний буфер байт
        int count; // к-сть елементів у масиві AI2

        // Зчитати кількість чисел
        AB2 = new byte[sizeof(int)]; // виділити пам'ять для числа типу int
        fs.Read(AB2, 0, AB2.Length);
        count = BitConverter.ToInt32(AB2, 0); // зчитати к-сть елементів у масиві AI2

        // Виділити пам'ять для масиву AI2
        AI2 = new int[count];

        // Цикл поелементного зчитування чисел в масив AI2
        for (int i = 0; i < AI2.Length; i++)
        {
          // Використати попередньо виділену пам'ять для числа типу int
          fs.Read(AB2, 0, AB2.Length);
          AI2[i] = BitConverter.ToInt32(AB2, 0);
        }

        // Вивести масив AI2 для перевірки
        for (int i = 0; i < AI2.Length; i++)
        {
          Console.Write("{0} ", AI2[i]);
        }
      }
    }
  }
}

Результат виконання програми

1 3 8 4 2 6

 

3. Приклад запису/читання масиву рядків string[]

У прикладі продемонстровано запис масиву рядків у файл та його читання.

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

namespace ConsoleApp10
{
  class Program
  {
    static void Main(string[] args)
    {
      // Запис масиву рядків типу string[] у файл "strings.bin"
      using (FileStream fw = new FileStream("strings.bin", FileMode.Create, FileAccess.Write))
      {
        // Масив, який потрібно записати у файл
        string[] AS = { "Delphi", "Java", "C#", "Python", "C++" };

        // Допоміжний буфер типу byte[]
        byte[] AB;

        // Спочатку потрібно записати кількість рядків,
        // для цього можна скористатись класом BitConverter.
        AB = BitConverter.GetBytes(AS.Length);
        fw.Write(AB, 0, AB.Length);

        // Цикл запису рядків
        for (int i = 0; i < AS.Length; i++)
        {
          // Спочатку записати довжину рядка
          AB = BitConverter.GetBytes(AS[i].Length);
          fw.Write(AB, 0, AB.Length);

          // Щоб записати рядок, потрібно використати клас Encoding з
          // простору імен System.Text, тому що рядок можна записувати
          // у різних системах кодування.
          AB = Encoding.UTF8.GetBytes(AS[i]); // система кодування UTF-8
          fw.Write(AB, 0, AB.Length);
        }
      }

      // Читання рядків типу string[] з файлу "strings.bin"
      using (FileStream fr = new FileStream("strings.bin", FileMode.Open, FileAccess.Read))
      {
        string[] AS2; // масив - результат
        byte[] AB2; // допоміжний буфер байт
        int count; // к-сть елементів у масиві AS2
        int len; // додаткова змінна - довжина рядка

        // Зчитати кількість рядків - count
        AB2 = new byte[sizeof(int)]; // виділити пам'ять для числа типу int
        fr.Read(AB2, 0, AB2.Length);
        count = BitConverter.ToInt32(AB2, 0);

        // Виділити пам'ять для масиву AS2
        AS2 = new string[count];

        // Цикл поелементного зчитування чисел в масив AS2
        for (int i = 0; i < AS2.Length; i++)
        {
          // Зчитати довжину рядка AS2[i] в байтах
          AB2 = new byte[sizeof(int)];
          fr.Read(AB2, 0, AB2.Length);
          len = BitConverter.ToInt32(AB2, 0); // len - довжина рядка AS2[i]

          // Зчитати рядок AS2[i]
          AB2 = new byte[len]; // виділити пам'ять для len байт
          fr.Read(AB2, 0, AB2.Length); // зчитати в буфер AB2

          // конвертування string <= byte[]
          AS2[i] = "";
          for (int j = 0; j < AB2.Length; j++)
            AS2[i] = AS2[i] + (char)AB2[j];
        }

        // Вивести масив AS2 для перевірки
        for (int i = 0; i < AS2.Length; i++)
          Console.WriteLine(AS2[i]);
      }
    }
  }
}

Результат виконання програми

Delphi
Java
C#
Python
C++

 

4. Приклад запису/читання масиву екземплярів класу Car (Автомобіль)

Умова задачі. Задано клас Car, який містить наступні члени даних:

  • model – марка автомобіля;
  • volume – об’єм двигуна;
  • year – рік випуску.

Також клас Car містить властивості доступу до членів даних та спеціальні функції класу:

  • конструктор;
  • властивості Model, Volume, Year.

Потрібно реалізувати запис масиву екземплярів типу Car[] у файл та його зчитування з подальшим виведенням результату.

Розв’язок. Текст програми, що розв’язує дану задачу наступний.

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

namespace ConsoleApp10
{
  // Клас, що описує автомобіль
  class Car
  {
    // Внутрішні члени даних класу
    private string model;
    private float volume;
    private int year;

    // Конструктор
    public Car(string model, float volume, int year)
    {
      this.model = model;
      this.volume = volume;
      this.year = year;
    }

    // Методи доступу
    public string Model
    {
      get { return model; }
      set { model = value; }
    }

    public float Volume
    {
      get { return volume; }
      set { volume = value; }
    }

    public int Year
    {
      get { return year; }
      set { year = value; }
    }
  }

  class Program
  {
    static void Main(string[] args)
    {
      // Запис масиву класів Car[] у файл "cars.bin"
      using (FileStream fw = new FileStream("cars.bin", FileMode.Create, FileAccess.Write))
      {
        // Масив, який потрібно записати у файл
        Car[] cars = {
                       new Car("Volvo", 2.8f, 2018),
                       new Car("Renault", 0.9f, 2017),
                       new Car("Audi", 12.2f, 2030)
        };

        // Допоміжний буфер типу byte[]
        byte[] AB;

        // Спочатку потрібно записати кількість елементів масиву cars
        AB = BitConverter.GetBytes(cars.Length);
        fw.Write(AB, 0, AB.Length);

        // Цикл запису елементів масиву cars
        for (int i = 0; i < cars.Length; i++)
        {
          // 1. Запис рядка model
          // Спочатку записати довжину рядка cars[i].Model
          AB = BitConverter.GetBytes(cars[i].Model.Length);
          fw.Write(AB, 0, AB.Length);

          // Щоб записати рядок, потрібно використати клас Encoding
          // з простору імен System.Text
          AB = Encoding.Default.GetBytes(cars[i].Model);
          fw.Write(AB, 0, AB.Length);

          // 2. Запис об'єму двигуна
          AB = BitConverter.GetBytes(cars[i].Volume);
          fw.Write(AB, 0, AB.Length);

          // 3. Запис року випуску
          AB = BitConverter.GetBytes(cars[i].Year);
          fw.Write(AB, 0, AB.Length);
        }
      }

      // Читання масиву типу Car[] з файлу "cars.bin"
      using (FileStream fr = new FileStream("cars.bin", FileMode.Open, FileAccess.Read))
      {
        Car[] cars2; // масив - результат
        byte[] AB2; // допоміжний буфер байт
        int count; // к-сть елементів у масиві cars2
        int len; // додаткова змінна - довжина рядка

        // Зчитати кількість елементів у масиві cars2 - count
        AB2 = new byte[sizeof(int)]; // виділити пам'ять для числа типу int
        fr.Read(AB2, 0, AB2.Length);
        count = BitConverter.ToInt32(AB2, 0);

        // Виділити пам'ять для масиву cars2
        cars2 = new Car[count];

        // Оголосити додаткові змінні, які будуть дублювати внутрішні дані класу
        string model; // марка автомобіля
        float volume; // об'єм двигуна
        int year; // рік випуску

        // Цикл поелементного зчитування екземплярів типу Car у масив cars2
        for (int i = 0; i < cars2.Length; i++)
        {
          // 1. Зчитати рядок Model
          // Зчитати довжину рядка cars2[i].Model в байтах
          AB2 = new byte[sizeof(int)];
          fr.Read(AB2, 0, AB2.Length);
          len = BitConverter.ToInt32(AB2, 0); // len - довжина рядка cars2[i].Model

          // Зчитати рядок
          AB2 = new byte[len]; // виділити пам'ять для len байт
          fr.Read(AB2, 0, AB2.Length); // зчитати в буфер AB2

          // конвертування string <= byte[]
          model = "";
          for (int j = 0; j < AB2.Length; j++)
            model += (char)AB2[j];

          // 2. Зчитати об'єм двигуна volume
          AB2 = new byte[sizeof(float)];
          fr.Read(AB2, 0, AB2.Length);
          volume = BitConverter.ToSingle(AB2);

          // 3. Зчитати рік випуску year
          AB2 = new byte[sizeof(int)];
          fr.Read(AB2, 0, AB2.Length);
          year = BitConverter.ToInt32(AB2);

          // 4. Створити екземпляр класу cars2[i]
          cars2[i] = new Car(model, volume, year);
        }

        // Вивести масив cars2 для перевірки
        for (int i = 0; i < cars2.Length; i++)
        {
          Console.WriteLine("Model = {0}, Volume = {1}, Year = {2}",
          cars2[i].Model, cars2[i].Volume, cars2[i].Year);
        }
      }
    }
  }
}

Результат виконання програми

Model = Volvo, Volume = 2.8, Year = 2018
Model = Renault, Volume = 0.9, Year = 2017
Model = Audi, Volume = 12.2, Year = 2030

 

5. Приклад перезаписування у файлі значень масиву типу double[], які лежать на парних позиціях (0, 2, 4, …). Демонстрація використання методу Seek()

У прикладі продемонстровано перезаписування даних безпосередньо у файлі. Як приклад, записується та зчитується масив чисел типу double[]. Перезаписуються числа, які лежать на парних позиціях. Одночасне читання даних з файлу та їх запис у файл можливе в режимі доступу FileAccess.ReadWrite.

using System;
using System.IO;

namespace ConsoleApp10
{
  class Program
  {
    static void Main(string[] args)
    {
      // Запис масиву типу double[] у файл "doubles.bin"
      using (FileStream fw = new FileStream("doubles.bin", FileMode.Create, FileAccess.Write))
      {
        // Масив, який потрібно записати у файл
        double[] AD = { 2.8, 3.3, 1.7, 3.8, 4.3, 6.1 };

        // Допоміжний буфер типу byte[]
        byte[] AB;

        // Спочатку потрібно записати кількість елементів масиву AD
        AB = BitConverter.GetBytes(AD.Length);
        fw.Write(AB, 0, AB.Length);

        // Цикл запису елементів масиву AD
        for (int i = 0; i < AD.Length; i++)
        {
          AB = BitConverter.GetBytes(AD[i]); // byte[] <= double
          fw.Write(AB, 0, AB.Length); // fw <= byte[]
        }
      }

      // Перезаписати числа в файлі, які лежать на парних позиціях
      using (FileStream fs = new FileStream("doubles.bin", FileMode.Open, FileAccess.ReadWrite))
      {
        // Зчитати кількість елементів у масиві
        byte[] AB = new byte[sizeof(int)];
        fs.Read(AB, 0, AB.Length);
        int count = BitConverter.ToInt32(AB);

        // Цикл обходу елементів у файлі,
        // елементи на непарних позиціях пропускаються
        for (int i = 1; i <= count; i++)
          // якщо непарна позиція, то перемотати покажчик запису/читання у файлі
          if (i % 2 == 1)
            fs.Seek(sizeof(double), SeekOrigin.Current); // пропустити число типу double
          else
          {
            // у парну позицію в файлі записати випадкове число від 0 до 10
            double num = (double)(new Random()).Next(0, 10);
            AB = BitConverter.GetBytes(num);
            fs.Write(AB, 0, AB.Length);
          }
      }

      // Читання масиву типу double[] з файлу "doubles.bin"
      using (FileStream fr = new FileStream("doubles.bin", FileMode.Open, FileAccess.Read))
      {
        double[] AD2; // масив - результат
        byte[] AB2; // допоміжний буфер байт
        int count; // к-сть елементів у масиві AD2

        // Зчитати кількість елементів у масиві AD2 - count
        AB2 = new byte[sizeof(int)]; // виділити пам'ять для числа типу int
        fr.Read(AB2, 0, AB2.Length);
        count = BitConverter.ToInt32(AB2, 0);

        // Виділити пам'ять для масиву AD2
        AD2 = new double[count];

        // Цикл поелементного зчитування елементів double з файлу
        // та запис їх у масив AD2
        for (int i = 0; i < AD2.Length; i++)
        {
          AB2 = new byte[sizeof(double)];
          fr.Read(AB2, 0, AB2.Length);
          AD2[i] = BitConverter.ToDouble(AB2);
        }

        // Вивести масив AD2
        for (int i = 0; i < AD2.Length; i++)
          Console.Write("{0:f1} ", AD2[i]);
      }
    }
  }
}

Результат виконання програми

2.8 5.0 1.7 5.0 4.3 8.0

 


Зв’язані теми