В данной статье я бы хотел поговорить о том, что такое сериализация в C# и для чего она нужна.
Сериализация — это представление объекта в виде потока байтов. Десериализация — это восстановление объекта и его данных из потока байтов. Потоком может выступать память, файл или сетевое соединение.
С помощью сериализации, программист может сохранить большие объемы разных данных с минимальными усилиями.
Форматы сериализации
1. Бинарная. В данном случае данные объекта представляются в бинарной форме. Это наиболее оптимальный вариант сериализации с точки зрения скорости и размера.
Недостаток данного вида заключается в его привязке к платформе. Допустим: вы передали данные другому программисту, у которого такая же платформа .NET и такая же версия этой платформы. В этом случае он сможет десериализовать данные, в противном случае — нет.
2. JSON — JavaScript Object Notation. Данный вид сериализации особенно удобен для передачи данных межу веб-приложениями. Если посмотреть json-формат данных, то мы увидим, что они представляют из себя javascript-объекты. Можно взять скопировать и вставить в Javascript-код, и это всё будет работать.
3. XML (eXtensible Markup Language — расширяемый язык разметки). Данный тип сериализации представляет объект в формате XML.
4. Можно написать свой собственный сериализатор, который будет представлять объекты в том виде, в котором вам нужно.
Минимальные действия, которые необходимо сделать, чтобы объекты класса были сериализуемы — это повесить на класс атрибут Serializable. По умолчанию, при создании класса, он не считается сериализуемым. При попытке сериализовать объект такого класса вылетит «Exception».
Процесс сериализации объектов
Представим, что у нас есть класс UserSettings, содержащий параметры, установленные пользователем. Чтобы этот класс можно было сериализовать, его нужно снабдить атрибутом Serializable:
[Serializable]
{
public string WorkDir = "C:\temp";
public int TimeOut = 2000;
}
Теперь давайте посмотрим, как сериализовать этот класс. Нужно создать объект класса:
UserSettings currentSettings = new UserSettings();
currentSettings.TimeOut = 1000; // устанавливаем конкретное значение
Для сериализации нужно создать объект типа BinaryFormatter:
using System.Runtime;
...
BinaryFormatter bf = new BinaryFormatter();
using (Stream fs = new FileStream("settings.dat", FileMode.Open.
Create, FileAccess.Write, FileShare.None))
{
bf.Serialize(fs, currentSettings);
}
Для десериализации нужно выполнить метод Deserialize():
FileStream fs = new FileStream("settings.dat", FileMode.Open);
try
{
BinaryFormatter bf = new BinarryFormatter();
currentSettings = (UserSettings)bf.Deserialize(fs);
}
catch (SerializationException e)
{
Console.WriteLine("Ошибка. Причина: " + e.Message);
throw;
}
finally
{
fs.Close();
}
Для десериализации объекта первым делом мы открываем файл для чтения. Далее создаем новый объект класса BinaryFormatter и дериализируем поток fs. Если в результате возникнет исключение, то мы выводим об этом сообщение. Блок finally позволяет в любом случае закрыть поток fs и освободить ресурсы.
Рассмотрим пример
Для бинарной сериализации применяется класс BinaryFormatter:
using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
namespace Serialization
{
[Serializable]
class Person
{
public string Name { get; set; }
public int Age { get; set; }
public Person(string name, int age)
{
Name = name;
Age = age;
}
}
class Program
{
static void Main(string[] args)
{
// объект для сериализации
Person person = new Person("Tom", 29);
Console.WriteLine("Объект создан");
// создаем объект BinaryFormatter
BinaryFormatter formatter = new BinaryFormatter();
// получаем поток, куда будем записывать сериализованный объект
using (FileStream fs = new FileStream("people.dat", FileMode.OpenOrCreate))
{
formatter.Serialize(fs, person);
Console.WriteLine("Объект сериализован");
}
// десериализация из файла people.dat
using (FileStream fs = new FileStream("people.dat", FileMode.OpenOrCreate))
{
Person newPerson = (Person)formatter.Deserialize(fs);
Console.WriteLine("Объект десериализован");
Console.WriteLine("Имя: {0} --- Возраст: {1}", newPerson.Name, newPerson.Age);
}
Console.ReadLine();
}
}
}
В нашем примере мы проводим сериализацию с помощью класса BinaryFormatter (создаем файл people.dat и заносим в него объект) и затем проводим десериализацию из файла people.dat.