Языки программирования

Сериализация объектов

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