Как быстро сохранить / загрузить экземпляр класса в файл - PullRequest
9 голосов
/ 24 ноября 2010

В моем приложении несколько коллекций классов / структур.

Класс - это просто класс с полями

class A
{
  public int somevalue;
  public string someothervalue
}

И моя коллекция

List<A> _myList;

Мне нужно сохранить _myList и загрузить. Я просто хочу сохранить все поля класса в файл и загрузить. Я не хочу тратить время на написание своего собственного сохранения / загрузки. Есть ли в .NET инструменты, которые могут мне помочь? Мне плевать на формат файла.

Ответы [ 6 ]

14 голосов
/ 15 марта 2014

Я только что написал сообщение в блоге о сохранении данных объекта в двоичном, XML или Json ;хорошо писать объект или список объектов в файл, который есть.Вот функции, чтобы сделать это в различных форматах.См. Мой пост в блоге для получения дополнительной информации.

Двоичный файл

/// <summary>
/// Writes the given object instance to a binary file.
/// <para>Object type (and all child types) must be decorated with the [Serializable] attribute.</para>
/// <para>To prevent a variable from being serialized, decorate it with the [NonSerialized] attribute; cannot be applied to properties.</para>
/// </summary>
/// <typeparam name="T">The type of object being written to the XML file.</typeparam>
/// <param name="filePath">The file path to write the object instance to.</param>
/// <param name="objectToWrite">The object instance to write to the XML file.</param>
/// <param name="append">If false the file will be overwritten if it already exists. If true the contents will be appended to the file.</param>
public static void WriteToBinaryFile<T>(string filePath, T objectToWrite, bool append = false)
{
    using (Stream stream = File.Open(filePath, append ? FileMode.Append : FileMode.Create))
    {
        var binaryFormatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
        binaryFormatter.Serialize(stream, objectToWrite);
    }
}

/// <summary>
/// Reads an object instance from a binary file.
/// </summary>
/// <typeparam name="T">The type of object to read from the XML.</typeparam>
/// <param name="filePath">The file path to read the object instance from.</param>
/// <returns>Returns a new instance of the object read from the binary file.</returns>
public static T ReadFromBinaryFile<T>(string filePath)
{
    using (Stream stream = File.Open(filePath, FileMode.Open))
    {
        var binaryFormatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
        return (T)binaryFormatter.Deserialize(stream);
    }
}

XML

Требуется, чтобы сборка System.Xml была включена в ваш проект.

/// <summary>
/// Writes the given object instance to an XML file.
/// <para>Only Public properties and variables will be written to the file. These can be any type though, even other classes.</para>
/// <para>If there are public properties/variables that you do not want written to the file, decorate them with the [XmlIgnore] attribute.</para>
/// <para>Object type must have a parameterless constructor.</para>
/// </summary>
/// <typeparam name="T">The type of object being written to the file.</typeparam>
/// <param name="filePath">The file path to write the object instance to.</param>
/// <param name="objectToWrite">The object instance to write to the file.</param>
/// <param name="append">If false the file will be overwritten if it already exists. If true the contents will be appended to the file.</param>
public static void WriteToXmlFile<T>(string filePath, T objectToWrite, bool append = false) where T : new()
{
    TextWriter writer = null;
    try
    {
        var serializer = new XmlSerializer(typeof(T));
        writer = new StreamWriter(filePath, append);
        serializer.Serialize(writer, objectToWrite);
    }
    finally
    {
        if (writer != null)
            writer.Close();
    }
}

/// <summary>
/// Reads an object instance from an XML file.
/// <para>Object type must have a parameterless constructor.</para>
/// </summary>
/// <typeparam name="T">The type of object to read from the file.</typeparam>
/// <param name="filePath">The file path to read the object instance from.</param>
/// <returns>Returns a new instance of the object read from the XML file.</returns>
public static T ReadFromXmlFile<T>(string filePath) where T : new()
{
    TextReader reader = null;
    try
    {
        var serializer = new XmlSerializer(typeof(T));
        reader = new StreamReader(filePath);
        return (T)serializer.Deserialize(reader);
    }
    finally
    {
        if (reader != null)
            reader.Close();
    }
}

Json

Вы должны включить ссылку на сборку Newtonsoft.Json, которую можно получить из пакета Json.NET NuGet .

/// <summary>
/// Writes the given object instance to a Json file.
/// <para>Object type must have a parameterless constructor.</para>
/// <para>Only Public properties and variables will be written to the file. These can be any type though, even other classes.</para>
/// <para>If there are public properties/variables that you do not want written to the file, decorate them with the [JsonIgnore] attribute.</para>
/// </summary>
/// <typeparam name="T">The type of object being written to the file.</typeparam>
/// <param name="filePath">The file path to write the object instance to.</param>
/// <param name="objectToWrite">The object instance to write to the file.</param>
/// <param name="append">If false the file will be overwritten if it already exists. If true the contents will be appended to the file.</param>
public static void WriteToJsonFile<T>(string filePath, T objectToWrite, bool append = false) where T : new()
{
    TextWriter writer = null;
    try
    {
        var contentsToWriteToFile = JsonConvert.SerializeObject(objectToWrite);
        writer = new StreamWriter(filePath, append);
        writer.Write(contentsToWriteToFile);
    }
    finally
    {
        if (writer != null)
            writer.Close();
    }
}

/// <summary>
/// Reads an object instance from an Json file.
/// <para>Object type must have a parameterless constructor.</para>
/// </summary>
/// <typeparam name="T">The type of object to read from the file.</typeparam>
/// <param name="filePath">The file path to read the object instance from.</param>
/// <returns>Returns a new instance of the object read from the Json file.</returns>
public static T ReadFromJsonFile<T>(string filePath) where T : new()
{
    TextReader reader = null;
    try
    {
        reader = new StreamReader(filePath);
        var fileContents = reader.ReadToEnd();
        return JsonConvert.DeserializeObject<T>(fileContents);
    }
    finally
    {
        if (reader != null)
            reader.Close();
    }
}

Пример

// Write the list of objects to a file.
WriteToXmlFile<List<A>>("C:\myObjects.txt", _myList);

// Read the list of objects from the file back into a variable.
List<A> _myList = ReadFromXmlFile<List<A>>("C:\myObjects.txt");
9 голосов
/ 24 ноября 2010

XMLSerializer не сложно использовать.Пока ваши объекты не огромные, это довольно быстро.Я сериализую некоторые огромные объекты в нескольких моих приложениях.Это занимает вечность, и в результате файлы становятся почти 100 мегабайтами, но они доступны для редактирования, если мне нужно кое-что настроить.Плюс не имеет значения, добавляю ли я поля к своим объектам.Сериализованные файлы старой версии объекта по-прежнему десериализованы должным образом. Я выполняю сериализацию в отдельном потоке, поэтому не имеет значения, сколько времени это займет в моем случае.Предостережение заключается в том, что ваш класс A должен иметь конструктор для работы XMLSerialziation.

Вот некоторый рабочий код, который я использую для сериализации / десериализации с обработкой ошибок, разорванной для удобства чтения ...

private List<A> Load()
{
    string file = "filepath";
    List<A> listofa = new List<A>();
    XmlSerializer formatter = new XmlSerializer(A.GetType());
    FileStream aFile = new FileStream(file, FileMode.Open);
    byte[] buffer = new byte[aFile.Length];
    aFile.Read(buffer, 0, (int)aFile.Length);
    MemoryStream stream = new MemoryStream(buffer);
    return (List<A>)formatter.Deserialize(stream);
}


private void Save(List<A> listofa)
{
    string path = "filepath";
    FileStream outFile = File.Create(path);
    XmlSerializer formatter = new XmlSerializer(A.GetType());
    formatter.Serialize(outFile, listofa);
}
2 голосов
/ 24 ноября 2010

Существует много сериализаторов:

Часть .net Framework

  • XmlSerializer (стандартизированный формат, медленный и подробный)
  • BinarySerializer (собственный формат, средняя скорость, поддерживает циклические графы , сериализует поля вместо свойств => надоедливое управление версиями )

третье лицо:

  • Json-Serializer (стандартизированный формат, текстовый, короче xml)
  • ProtoBuf-Serializer (стандартизированный формат, бинарный, очень быстрый)

Я бы, вероятно, использовал сериализатор ProtoBuf, если файл может быть двоичным, и сериализатор json, если он должен быть простым текстом.

1 голос
/ 21 февраля 2015

Старая тема, но я изменил ответ Тима Кокера, приведенный выше, чтобы использовать блоки using для правильной утилизации объектов потока и сохранения только одного экземпляра класса за раз:

public static T Load<T>(string FileSpec) {
    XmlSerializer formatter = new XmlSerializer(typeof(T));

    using (FileStream aFile = new FileStream(FileSpec, FileMode.Open)) {
        byte[] buffer = new byte[aFile.Length];
        aFile.Read(buffer, 0, (int)aFile.Length);

        using (MemoryStream stream = new MemoryStream(buffer)) {
            return (T)formatter.Deserialize(stream);
        }
    }
}

public static void Save<T>(T ToSerialize, string FileSpec) {
    Directory.CreateDirectory(FileSpec.Substring(0, FileSpec.LastIndexOf('\\')));
    FileStream outFile = File.Create(FileSpec);
    XmlSerializer formatter = new XmlSerializer(typeof(T));

    formatter.Serialize(outFile, ToSerialize);
}
1 голос
/ 24 ноября 2010

Вы можете сериализовать ваш List<> с помощью XML-сериализатора или двоичного сериализатора и сохранить сериализованный список в файл.

Позже вы можете прочитать содержимое этого файла и получить исходный список.

Сделайте ваш тип, для которого вы создаете список [Serializable]

1 голос
/ 24 ноября 2010

Я обычно использую XML Serilizer, он быстрый, простой в реализации и хранит объекты в удобном для чтения виде, вы можете видеть хороший пример .

Вы можете использовать двоичный файлСериализация, если вы хотите более эффективное решение по размерам.(например, если вы хотите передать сериализацию по сети.)

РЕДАКТИРОВАТЬ: Чтобы получить больше контроля над сериализуемыми элементами, взгляните на этот пример

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...