BinaryFormatter и SoapFormatter
54C# и .NET --- Многопоточность и файлы --- BinaryFormatter и SoapFormatter
Чтобы проиллюстрировать, насколько просто сохранить экземпляр JamesBondCar (пример из предыдущих статей) в физическом файле, воспользуемся типом BinaryFormatter. Двумя ключевыми методами типа BinaryFormatter, о которых следует знать, являются Serialize() и Deserialize():
Serialize() сохраняет граф объектов в указанный поток в виде последовательности байтов;
Deserialize() преобразует сохраненную последовательность байт в граф объектов.
Предположим, что после создания экземпляра JamesBondCar и модификации некоторых данных состояния требуется сохранить этот экземпляр в файле *.dat. Первая задача — создание самого файла *.dat. Для этого можно создать экземпляр типа System.IO.FileStream. Затем следует создать экземпляр BinaryFormatter и передать ему FileStream и граф объектов для сохранения. Взгляните на следующий метод Main():
using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
namespace Serialize
{
class Program
{
static void Main()
{
JamesBondClass jbc = new JamesBondClass();
jbc.canFly = true;
jbc.canSubmerge = false;
jbc.theRadio.stationPresets = new double[] { 89.3, 105.1, 97.1 };
jbc.theRadio.hasTweeters = true;
// Сохранить объект в указанном файле в двоичном формате
SaveBinaryFormat(jbc, "carData.dat");
Console.ReadLine();
}
static void SaveBinaryFormat(object objGraph, string fileName)
{
BinaryFormatter binFormat = new BinaryFormatter();
using (Stream fStream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None))
{
binFormat.Serialize(fStream, objGraph);
}
Console.WriteLine("--> Сохранение объекта в Binary format");
}
}
...
Как видите, метод BinaryFormatter.Serialize() — это член, отвечающий за составление графа объектов и передачу последовательности байт в некоторый объект унаследованного от Stream типа. В данном случае поток представляет физический файл. Однако можно также сериализовать объекты в любой тип-наследник Stream, представляющий область памяти, сетевой поток и т.п.
После выполнения программы можно просмотреть содержимое файла carData.dat, представляющее этот экземпляр JamesBondCar, в папке bin\Debug текущего проекта. На рисунке показан этот файл, открытый в Visual Studio 2010:

Теперь предположим, что необходимо прочитать сохраненный объект JamesBondCar из двоичного файла обратно в объектную переменную. После открытия файла carData.dat (методом File.OpenRead()) просто вызовите метод Deserialize() класса BinaryFormatter. Имейте в виду, что Deserialize() возвращает объект общего типа System.Object, так что понадобится применить явное приведение, как показано ниже:
static void LoadFromBinaryFile(string fileName)
{
BinaryFormatter binFormat = new BinaryFormatter();
using (Stream fStream = File.OpenRead(fileName))
{
JamesBondClass carFromDisk =
(JamesBondClass)binFormat.Deserialize(fStream);
Console.WriteLine(carFromDisk.canFly);
}
}
Обратите внимание, что при вызове Deserialize() ему передается тип-наследник Stream, представляющий местоположение сохраненного графа объектов. Приведя возвращенный объект к правильному типу, вы получаете объект в том состоянии, в каком он был на момент сохранения.
Следующий форматер, которым мы воспользуемся, будет SoapFormatter, сериализующий данные в подходящем конверте SOAP. Протокол SOAP (Simple Object Access Protocol — простой протокол доступа к объектам) определяет стандартный процесс вызова методов в независящей от платформы и операционной системы манере.
Предполагая, что ссылка на сборку System.Runtime.Serialization.Formatters.Soap.dll установлена, а пространство имен System.Runtime.Serialization.Formatters.Soap импортировано, для сохранения и извлечения JamesBondCar в виде сообщения SOAP можно просто заменить в предыдущем примере все вхождения BinaryFormatter на SoapFormatter. Ниже показан новый метод класса Program, который сериализует объект в локальный файл:
static void SoapWriteFile(object objGraph, string fileName)
{
SoapFormatter soapFormatter = new SoapFormatter();
using (Stream fStream = new FileStream(fileName,
FileMode.Create, FileAccess.Write, FileShare.None))
{
soapFormatter.Serialize(fStream, objGraph);
}
Console.WriteLine("--> Сохранение объекта в SOAP-формат");
}
