Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

lec

.pdf
Скачиваний:
25
Добавлен:
24.03.2015
Размер:
3.43 Mб
Скачать

{

fs = new FileStream(@"c:\Temp\GroupDirect.bin", FileMode.Create,

Fil-

eAccess.Write);

dataOut = new BinaryWriter(fs, System.Text.Encoding.Unicode);

for (int i = 0; i < tableStd.Count; i++)

{

std = (Student)tableStd[i]; std.Show();

dataOut.Write("Студент"); fio = std.fio.PadRight(15); dataOut.Write(fio); dataOut.Write(std.yar); dataOut.Write(std.ball);

}

}

catch (Exception e)

{

Console.WriteLine("Error: " + e.Message); return;

}

fs.Close();

}

}

Задача 2.

/*

Вывести на экран информацию из файла С:\Temp\GroupDirect.bin о студентах, заданных порядковым номером.

Номера студентов ввести с клавиатуры. Первый студент имеет номер 1.

Признаком конца списка является ввод 0 в качестве номера студента. */

using System; using System.IO;

using System.Collections; using System.Text;

class Example

{

public static void Main()

{

string fio; uint god; float ball;

uint N; // порядковый номер студента в файле

string str;

191

string path = @"c:\Temp\GroupDirect.bin";

uint kRec; // количество записей const uint lRec = (7*2+1)+(15*2+1)+4+4; // длина записи

// (Сту-

дент,fio,god,ball)

if (!File.Exists(path))

{

Console.WriteLine("Файл отсутствует."); return;

}

FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read); BinaryReader dataIn = new BinaryReader(fs, Encoding.Unicode);

kRec = (uint)fs.Length / lRec; //кол.записей = длина файла /

длина записи

Console.WriteLine("В файле студентов: {0}", kRec);

while (true)

{

Console.WriteLine("\n__________________________________________"); Console.Write("Введите номер студента (0 - конец поиска): ");

try

{

N = uint.Parse(Console.ReadLine());

}

catch

{

Console.WriteLine("==ОШИБКА== Повторите ввод целого числа."); continue;

}

if (N == 0) break;

if (N > kRec)

{

Console.WriteLine("\n==ОШИБКА== Студента с таким номером нет."); Console.WriteLine(" Всего в файле студентов: {0}", kRec); continue;

}

// Позиционируем указатель записи fs.Seek((N - 1) * lRec, SeekOrigin.Begin); try

{

str = dataIn.ReadString(); fio = dataIn.ReadString(); god = dataIn.ReadUInt32(); ball = dataIn.ReadSingle();

Console.WriteLine("Студент {0}, год рождения {1}, ср.балл = {2}\n", fio, god, ball);

192

}

catch (Exception e)

{

Console.WriteLine("Error: " + e.Message); return;

}

}

fs.Close();

}

}

193

СЕРИАЛИЗАЦИЯ, ОПЕРАЦИИ С ФАЙЛАМИ И КАТАЛОГАМИ

1. Сохранение и восстановление объектов

Сохранение объектов представляет собой определенную проблему. Связано это с тем, что обычно переменные объекта являются недоступными в программе. Для решения этой проблемы создано пространство имен System.Runtime.Serialization с классами, используемыми для се-

риализации и десериализации объектов.

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

Десериализация — это процесс изъятия сохраненных сведений и создания из них объектов.

Для того чтобы объекты можно было сериализовать, его класс должен быть помечен атрибутом [Serializable].

По умолчанию CLR не предполагает, что объекты будут сохраняться в каком-либо хранилище (например, в файле на диске).

Для сериализации объекта нужно выполнить следующие шаги:

Пометить сериализуемый класс атрибутом [Serializable].

Создать байтовый поток.

Создать объект класса BinaryFormatter, управляющий сериализацией.

Вызвать метод Serialize() этого объекта для выполнения сериализации.

Для десериализации объектов нужно вместо метода Serialize() выполнить метод Deserialize() и привести воостанавливаемые объекты к требуемому типу.

// Сохранение объектов using System;

using System.IO;

using System.Runtime.Serialization;

using System.Runtime.Serialization.Formatters.Binary;

[Serializable]

 

 

class Customer

 

 

{

 

 

private int

CustomerNumber;

// N покупателя

private string CustomerName;

// Имя покупателя

private string CustomerCountry;

// Страна

public Customer (int Number, string Name, string Country)

{

this.CustomerNumber = Number; this.CustomerName = Name; this.CustomerCountry = Country;

}

194

public void WriteCustomer()

{

Console.WriteLine("Customer Number: " + CustomerNumber); Console.WriteLine("Customer Name: " + CustomerName); Console.WriteLine("Customer Country: " + CustomerCountry);

}

}

class SaveObj

{

public static void Main()

{

FileStream fs;

Customer Customer1 = new Customer (1, "Aлен Дилон", "Франция");

Customer Customer2 = new Customer (2, "Иванов", "Россия");

Customer1.WriteCustomer();

Customer2.WriteCustomer();

// Создание потока

fs = new FileStream ("c:\\Temp\\Customer.dat", FileMode.Create);

//Воспользуемся поддержкой двоичного форматирования в CLR BinaryFormatter sf = new BinaryFormatter();

//Сохраним объект в файле в двоичном виде

sf.Serialize (fs, Customer1); sf.Serialize (fs, Customer2); fs.Close();

// Восстановим из файла сериализованный объект

fs = new FileStream ("c:\\Temp\\Customer.dat", FileMode.Open);

Customer NewCustomer1 = (Customer)sf.Deserialize (fs);

NewCustomer1.WriteCustomer();

Customer NewCustomer2 = (Customer)sf.Deserialize (fs); NewCustomer2.WriteCustomer();

}

}

Если объект должен использоваться в другом приложении, лучшим выбором может оказаться не двоичный формат, а формат протокола SOAP (в виде XML-файла). SOAP – простой протокол доступа к объектам.

Для реализации этой задачи нужно:

Вместо пространства имен

System.Runtime.Serialization.Formatters.Binary использовать System.Runtime.Serialization.Formatters.Soap.

Вместо класса BinaryFormatter использовать класс SoapFormatter.

Файл создавать с расширением xml (необязательно).

195

// Сохранение объектов при помощи протокола SOAP

using System; using System.IO;

using System.Runtime.Serialization;

// using System.Runtime.Serialization.Formatters.Binary; using System.Runtime.Serialization.Formatters.Soap;

[Serializable]

 

 

class Customer

 

 

{

 

 

private int

CustomerNumber;

// N покупателя

private string CustomerName;

// Имя покупателя

private string CustomerCountry;

// Страна

public Customer (int Number, string Name, string Country)

{

this.CustomerNumber = Number; this.CustomerName = Name; this.CustomerCountry = Country;

}

public void WriteCustomer()

{

Console.WriteLine("Customer Number: " + CustomerNumber); Console.WriteLine("Customer Name: " + CustomerName); Console.WriteLine("Customer Country: " + CustomerCountry);

}

}

class SaveObj

{

public static void Main()

{

FileStream fs;

Customer Customer1 = new Customer(1, "Aлен Дилон", "Франция"); Customer Customer2 = new Customer(2, "Иванов", "Россия");

Customer1.WriteCustomer();

Customer2.WriteCustomer();

//Создание потока

//fs = new FileStream ("c:\\Temp\\Customer.dat", FileMode.Create); fs = new FileStream ("c:\\Temp\\Customer.xml", FileMode.Create);

//Воспользуемся поддержкой SOAP форматирования

//BinaryFormatter sf = new BinaryFormatter();

SoapFormatter sf = new SoapFormatter();

// Сохраним объект в файле в двоичном виде sf.Serialize (fs, Customer1);

sf.Serialize (fs, Customer2); fs.Close();

196

// Восстановим из файла сериализованный объект

fs = new FileStream ("c:\\Temp\\Customer.xml", FileMode.Open);

Customer NewCustomer1 = (Customer)sf.Deserialize (fs);

NewCustomer1.WriteCustomer();

Customer NewCustomer2 = (Customer)sf.Deserialize (fs); NewCustomer2.WriteCustomer();

}

}

Классы SoapFormatter и BinaryFormatter предоставляют возмож-

ности для сериализации не только отдельных объектов, но и более сложных структур, например хеш-таблиц.

Такие структуры должны реализовывать интерфейс ISerializable. Реализация интерфейса ISerializable необходима классу в том случае, если он хочет управлять обработкой своей сериализации. Все коллекции FCL реализуют указанный интерфейс.

Пример сериализации хеш-таблицы. using System;

using System.IO;

using System.Collections;

using System.Runtime.Serialization;

using System.Runtime.Serialization.Formatters.Binary;

public class App

{

[STAThread] static void Main()

{

Serialize();

Deserialize();

}

static void Serialize()

{

FileStream fs;

// Создать хеш-таблицу с ключем и полем данных. Hashtable addresses = new Hashtable();

addresses.Add ("Сергей", "Москва, ул Пирогова, д.17, кв.25"); addresses.Add ("Юлия", "Новгород, ул.Космонавтов, д. 24"); addresses.Add ("Николай", "Тула, пр-т Ленина, д.134, кв. 76");

fs = new FileStream ("C:\\Temp\\DataFile.dat", FileMode.Create);

BinaryFormatter bf = new BinaryFormatter(); try

{

bf.Serialize (fs, addresses);

197

}

catch (SerializationException e) // в пространстве System.Runtime.Serialization

{

Console.WriteLine ("Ошибка сериализации: " + e.Message); throw;

}

finally

{

fs.Close();

}

}

static void Deserialize()

{

FileStream fs;

Hashtable addresses = null;

// Open the file containing the data that you want to deserialize. fs = new FileStream ("C:\\Temp\\DataFile.dat", FileMode. Open);

try

{

BinaryFormatter bf = new BinaryFormatter();

addresses = (Hashtable)bf.Deserialize(fs);

}

catch (SerializationException e)

{

Console.WriteLine("Ошибка десериализации: " + e.Message); throw;

}

finally

{

fs.Close();

}

foreach (DictionaryEntry de in addresses)

{

Console.WriteLine("{0} живет в городе {1}.", de.Key, de.Value);

}

}

}

Другой способ сохранения объектов (без сериализации).

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

Set…().

198

Сериализация/десериализация графа объектов

Если сериализуемый объект содержит ссылки на другие сериализуемые объекты, которые в свою очередь так же содержат ссылки на сериализуемые объекты, то такая структура образует граф объектов.

При сериализации объекта, находящегося в вершине графа, будет сериализован весь граф.

рис.6

Произвольный доступ к сериализованным объектам.

Осуществляется так же, как и в случае хранения двоичных данных в файле.

Способ 1

Указатель поз.

0

 

Объект 1

 

Объект 2

 

• • •

 

Объект N

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

рис.7

Length(Объект) = const

Способ 2 Использование файла указателей (см. лекцию 3).

Пример произвольного доступа к объектам

/* У заданных студентов из файла С:\Temp\GroupSerial.bin заменить средние баллы. Фамилии студентов и их новые средние баллы ввести с клавиатуры.

Признаком конца списка является ввод Enter в качестве фамилии студента. Вывести файл на экран

*/

using System; using System.IO;

using System.Collections;

using System.Runtime.Serialization;

using System.Runtime.Serialization.Formatters.Binary;

199

[Serializable] class Student

{

public string fio; public uint yar; public float ball;

public Student(string f, uint y, float b)

{

fio = f; yar = y; ball = b;

}

public void Show()

{

Console.WriteLine("Студент {0}, год рождения {1}, ср.балл = {2}",

}

fio,

yar,

ball);

 

 

 

}

 

 

 

class Example1

 

 

 

{

 

 

 

public static void Main()

 

 

{

 

 

 

string

fio = " ";

 

 

Student

std;

 

 

float

newBall = 0;

uint

k;

long

pos;

string path = @"c:\Temp\GroupSerial.bin"; FileStream fs;

BinaryFormatter frm;

ArrayList tableStd = new ArrayList();

frm = new BinaryFormatter();

// Выборочная модификация объектов fs = new FileStream(path, FileMode.Open);

while (true)

{

Console.WriteLine("____________________________" + "______________________________");

Console.Write(

"Введите фамилию (пробел - конец поиска): "); fio = Console.ReadLine();

if (fio == " " || fio.Length == 0) break;

200

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]