В данной статье я бы хотел поговорить о том, что такое сериализация в 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.