- •Лабораторная работа №3. Ввод, вывод и сериализация объектов
- •1. Цель работы
- •2. Сведения из теории
- •2.1. Пространство имен System.Io
- •2.2. Классы потоков
- •2.3. Текстовые файлы
- •2.4. Двоичные файлы
- •2.5. Сериализация объектов
- •3. Пример выполнения работы
- •3.1. Визуальное проектирование диалогового окна
- •3.2. Проектирование программного кода
- •4. Задание для самостоятельной работы
3.2. Проектирование программного кода
Прежде всего, для обеспечения файлового ввода/вывода нужно подключить пространство имен System.IO, т.е. в начале файла с кодом программы написать:
using System.IO;
Описание создаваемых обработчиков событий начнем с метода-обработчика пункта меню «Сохранить…». В этом случае необходимо:
отобразить на экране диалоговое окно выбора файла для сохранения;
если пользователем в этом окне нажата кнопка ОК, то получить имя файла для сохранения;
создать поток вывода и связать его с этим файлом;
создать объект класса BinaryWriter для обеспечения записи в двоичный файл и связать его с потоком;
координаты каждой точки массива points записать в файл с помощью метода Write();
закрыть объект BinaryWriter и связанный с ним поток.
Листинг обработчика приведен ниже:
private void сохранитьToolStripMenuItem_Click(object sender, EventArgs e)
{
//отобразить диалоговое окно "Сохранить как..."
if (saveFileDialog1.ShowDialog() == DialogResult.OK)
{
//получить имя файла для сохранения
String FileName = saveFileDialog1.FileName;
//создать (поток) новый файл с указанным именем
FileStream myStream = new
FileStream(FileName,FileMode.Create);
//создать объект BinaryWriter и связать его с потоком
BinaryWriter BW = new BinaryWriter(myStream);
//просмотреть массив точек
foreach (Point p in points)
{
//записать координаты каждой точки в файл
BW.Write(p.x);
BW.Write(p.y);
}
BW.Close(); //закрыть BinaryWriter
myStream.Close(); //и поток, связанный с файлом
}
}
Метод-обработчик пункта меню «Открыть…» структурно похож на предыдущий за исключением использования компонента openFileDialog1 для получения имени открываемого файла и объекта класса BinaryReader для чтения данных из двоичного файла. Чтение данных из файла осуществляется с помощью метода ReadSingle(). Индикатором конца файла является равенство -1 результата вызова метода PeekChar(), который считывает один символ без удаления его из входного потока. Одновременно с чтением данные из файла добавляются в массив points и таблицу на форме:
private void открытьToolStripMenuItem_Click(object sender, EventArgs e)
{
//отобразить диалоговое окно "Открыть..."
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
//получить имя открываемого файла
String FileName = openFileDialog1.FileName;
//открыть поток (файл с указанным именем)
FileStream myStream = new FileStream(FileName,
FileMode.Open);
//создать объект BinaryReader и связать его с потоком
BinaryReader BR = new BinaryReader(myStream);
points.Clear(); //очистить массив точек
dataGridView1.Rows.Clear(); //и таблицу на форме
//пока не дощли до конца файла
while (BR.PeekChar() != -1)
{
//считать координаты очередной точки
float x = BR.ReadSingle();
float y = BR.ReadSingle();
//создать точку с этими координатами
Point p = new Point(x, y);
//добавить точку в массив
points.Add(p);
//и в таблицу на форме
dataGridView1.Rows.Add(p.x, p.y);
}
BR.Close(); //закрыть BinaryReader
myStream.Close(); //и поток, связанный с файлом
}
}
Принцип сохранения массива-результата в текстовом формате аналогичен сохранению в двоичном формате, только в данном случае вместо класса BinaryWriter используется класс StreamWriter. Для записи в файл здесь удобно использовать метод WriteLine(), чтобы координаты одной точки занимали отдельную строку. Листинг обработчика приведен ниже:
private void сохранитьРезультатToolStripMenuItem_Click(object sender, EventArgs e)
{
//отобразить диалоговое окно "Сохранить как..."
if (saveFileDialog1.ShowDialog() == DialogResult.OK)
{
//получить имя файла для сохранения
String FileName = saveFileDialog1.FileName;
//создать поток (новый файл с указанным именем)
FileStream myStream = new FileStream(FileName,
FileMode.Create);
//создать объект StreamWriter и связать его с потоком
StreamWriter SW = new StreamWriter(myStream);
//записать координаты точек в файл
foreach (Point p in res)
SW.WriteLine(p.x+" "+p.y);
SW.Close(); //закрыть StreamWriter
myStream.Close(); //и поток, связанный с файлом
}
}
Чтобы обеспечить сериализацию и десериализацию объектов классов, нужно подключить соответствующие пространства имен:
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization;
Для реализации процессов сериализации и десериализации объектов класса Point необходимо присвоить этому классу атрибут [Serializable]:
[Serializable]
class Point : IComparable
{
...
}
Оба процесса реализуются через объекты класса BinaryFormatter и их методы Serialize() и Deserialize():
private void сериализацияToolStripMenuItem_Click(object sender, EventArgs e)
{
//отобразить диалоговое окно "Сохранить как..."
if (saveFileDialog1.ShowDialog() == DialogResult.OK)
{
//получить имя файла для сохранения
String FileName = saveFileDialog1.FileName;
//создать поток (новый файл с указанным именем)
FileStream myStream = new FileStream(FileName,
FileMode.Create);
//создать объект BinaryFormatter для сериализации
BinaryFormatter myFormatter = new BinaryFormatter();
//произвести сериализацию (сохранение объекта в файл)
myFormatter.Serialize(myStream, points);
//закрыть поток, связанный с файлом
myStream.Close();
}
}
private void десериализацияToolStripMenuItem_Click(object sender, EventArgs e)
{
//отобразить диалоговое окно "Открыть..."
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
try
{
//получить имя открываемого файла
String FileName = openFileDialog1.FileName;
//открыть поток (файл с указанным именем)
FileStream myStream = new FileStream(FileName,
FileMode.Open);
//создать объект BinaryFormatter для десериализации
BinaryFormatter myFormatter = new BinaryFormatter();
//очистить массив точек
points.Clear();
//и таблицу на форме
dataGridView1.Rows.Clear();
//выполнить десериализацию (восстановление из файла)
points = (ArrayList)myFormatter.Deserialize(myStream);
//отобразить восстановленный массив на форме
foreach (Point p in points)
dataGridView1.Rows.Add(p.x, p.y);
//закрыть поток, связанный с файлом
myStream.Close();
}
catch (SerializationException)
{
MessageBox.Show("Неверный формат файла!!!");
}
}
}