Сохранение текущего состояния объектов в файлах

1. Цель работы. Получение навыков в разработке программ с использованием файлов, сохранения информации в них и работы с ними.

2. Общие сведения

При разработке приложений часто возникают две в общем случае схожие задачи: сохранить (прочитать) содержимое данных (файла) и сохранить (прочитать) текущее состояние объекта в файле или таблице базы данных. Несмотря на несомненную схожесть указанных задач, для решения каждой из них предусмотрены свои классы.

Техника работы с файлами зависит от типа файла (текстовый или двоичный). При работе с текстовыми файлами сначала создается поток класса FileStream. Данные записываются в файл с помощью вспомогательного объекта класса StreamWriter, а читаются объектом класса StreamReader. При создании объекта FileStream ему передаются имя файла и два параметра: FileMode, определяющий способ создания потока, и FileAccess, регулирующий доступ потока к данным.

Таблица1.

Значение параметра FileMode

Значение Описание
Append Добавляет записи в существующий файл или создает новый. Требует, чтобы параметр FileMode имел значение Write
Create Создает новый файл или переписывает существующий. Требует, чтобы параметр FileMode имел значение Write
CreateNew Создает новый файл, а если он уже существует, возникает исключение. Требует, чтобы параметр FileMode имел значение Write
Open Открывает существующий файл. Если файла нет, возникает исключение
OpenOrCreate Открывает существующий или создает новый файл, если он еще не создан
Truncate Открывает существующий файл и делает его размер равным нулю

Таблица2.

Значение параметра FileAccess

Значение Описание
Read Поток может читать данные
ReadWrite Поток может читать и записывать данные
Write Поток может записывать данные

Для потока существует понятие текущей записи — в эту запись помещаются данные и из нее они считываются. Положением текущей записи можно управлять с помощью метода Seek(), имеющего такую сигнатуру:

public virtual long Seek (int Offset, SeekOrigin Origin);

Здесь Offset — смещение относительно позиции, указанной параметром Origin.

Таблица3.

Значение параметра SeekOrigin

Значение Описание
Begin Соответствует началу потока
Current Соответствует текущей записи потока
End Соответствует концу потока

Физическая запись данных в файл реализуется в момент закрытия потока методом Close() или выталкиванием записей из промежуточного буфера методом Flush(). Во втором случае поток не закрывается и готов к продолжению операций.

Обработка двоичных файлов во многом подобна обработке текстовых: сначала создается поток, затем — объекты BinaryWriter или BinaryReader в зависимости от направления передачи данных (в файл или из файла).

C# поддерживает интересную технологию сохранения текущего состояния объекта на некотором носителе информации. Эта технология называется сериализацией объекта. Сериализованный объект может быть, например, передан по сети на другой компьютер и там восстановлен в первоначальном состоянии — этот процесс называется десериализацией.

Особенностью сериализации является то, что ее можно применять к классам, поддерживающим эту процедуру. Для этого класс должен объявляться с атрибутом [Serializable] или в его объявлении должно быть явное указание на то, что он исполняет интерфейс ISerializable. Лишь относительно небольшое количество (менее 40) стандартных классов реализуют данный интерфейс. Это, в основном, классы, используемые как хранилища данных.

Следующий пример иллюстрирует данную технологию.

using System;

using System.IO;

using System.Runtime.Serialization.Formatters.Binary;

namespace Project5

{

[Serializable]

class queue

{

private int q=50;

private char[] arrchar= new char[4] {'a','b','c','d'};

public int p;

public char ch;

}

[Serializable]

class queue1 : queue

{

private int r = 50;

public new int q=50;

public new char[] arrchar= new char[4] {'e','f','g','h'};

public queue1() {}

public queue1(int q, int i)

{ p = q*r;

ch = arrchar[i];

}

}

class Executer

{

[STAThread]

static void Main()

{

queue1 a = new queue1();

queue1 b = new queue1(50,2);

queue1 c = new queue1(500,1);

FileStream fs;

fs = new FileStream

("File_queue.bin",FileMode.Create,FileAccess.Write);

BinaryFormatter sw = new BinaryFormatter();

sw.Serialize(fs,b);

sw.Serialize(fs,c);

fs.Close();

fs = new FileStream

("File_queue.bin",FileMode.Open,FileAccess.Read);

long i=0,

j = fs.Length/231; //231 — количество байт занимаемых одним объектом класса queue1

while (i < j)

{

a = (queue1) sw.Deserialize(fs);

Console.WriteLine(a.p);

Console.WriteLine(a.ch);

i++;

}

fs.Close();

Console.ReadLine();

}

}

}

Постановка задачи

Создать объекты класса <имя класса> (класс и его поля задаются в соответствии с выбранным вариантом в лабораторной работе 1), причем объекты класса должны хранить данных о предметной области, связанные со свойствами предмета задания по варианту. Сохранить данные объекты в файле. Причем сохранить необходимо как отдельные объекты, так объект контейнерного типа, полученный в лабораторной работе 4. Считать сохраненные данные из файла и вывести их на экран.

Наши рекомендации