Примеры применения класса FileStream без использования дополнительных потоков (декораторов, адаптеров)
Перед изучением данной темы рекомендуется ознакомиться со следующими темами:
- Понятие потока. Архитектура потоков в C#. Потоки с опорными хранилищами. Потоки с декораторами. Адаптеры потоков
- Иерархия потоков с опорными хранилищами. Класc FileStream
Класс FileStream может быть применен автономно без использования дополнительных потоков адаптеров или декораторов. Для этого в классе есть все необходимые средства (методы). Основные методы класс наследует от базового класса Stream.
Содержание
- 1. Пример чтения/записи числа типа double в файл. Использование FileStream
- 2. Пример записи/чтения массива чисел типа int[]
- 3. Пример записи/чтения массива строк string[]
- 4. Пример записи/чтения массива экземпляров класса Car (автомобиль)
- 5. Пример перезаписи в файле значений массива типа double[], которые лежат на четных позициях (0, 2, 4, …). Демонстрация использования метода Seek()
- Связанные темы
Поиск на других ресурсах:
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
⇑
Связанные темы
- Иерархия потоков с опорными хранилищами. Класc FileStream
- Класс FileStream. Дополнительные опции записи/чтения. Перечисление FileOptions. Примеры
⇑