Serileştirilebilir nesne dosyaya / dosyadan nasıl kaydedilir / geri yüklenir?


96

Bir nesne listem var ve bunu bilgisayarımda bir yere kaydetmem gerekiyor. Bazı forumları okudum ve nesnenin olması gerektiğini biliyorum Serializable. Ama bir örnek alabilirsem güzel olur. Örneğin aşağıdakilere sahipsem:

[Serializable]
public class SomeClass
{
     public string someProperty { get; set; }
}

SomeClass object1 = new SomeClass { someProperty = "someString" };

Ama object1bilgisayarımda bir yere nasıl kaydedebilirim ve daha sonra nasıl alabilirim?


3
İşte bir dosya geçişinde
Brook

Yanıtlar:


145

Aşağıdakileri kullanabilirsiniz:

    /// <summary>
    /// Serializes an object.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="serializableObject"></param>
    /// <param name="fileName"></param>
    public void SerializeObject<T>(T serializableObject, string fileName)
    {
        if (serializableObject == null) { return; }

        try
        {
            XmlDocument xmlDocument = new XmlDocument();
            XmlSerializer serializer = new XmlSerializer(serializableObject.GetType());
            using (MemoryStream stream = new MemoryStream())
            {
                serializer.Serialize(stream, serializableObject);
                stream.Position = 0;
                xmlDocument.Load(stream);
                xmlDocument.Save(fileName);
            }
        }
        catch (Exception ex)
        {
            //Log exception here
        }
    }


    /// <summary>
    /// Deserializes an xml file into an object list
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="fileName"></param>
    /// <returns></returns>
    public T DeSerializeObject<T>(string fileName)
    {
        if (string.IsNullOrEmpty(fileName)) { return default(T); }

        T objectOut = default(T);

        try
        {
            XmlDocument xmlDocument = new XmlDocument();
            xmlDocument.Load(fileName);
            string xmlString = xmlDocument.OuterXml;

            using (StringReader read = new StringReader(xmlString))
            {
                Type outType = typeof(T);

                XmlSerializer serializer = new XmlSerializer(outType);
                using (XmlReader reader = new XmlTextReader(read))
                {
                    objectOut = (T)serializer.Deserialize(reader);
                }
            }
        }
        catch (Exception ex)
        {
            //Log exception here
        }

        return objectOut;
    }

1
Güzel! Her ne kadar string attributeXml = string.Empty;içinde DeSerializeObject); hiçbir zaman kullanılmaz
Jimbo

3
Kullanım bloğunuzdaki bir okuyucuda close yöntemini çağırmanıza gerek yok. Dispose () örtüktür ve açık Close () öncesinde blok içinde bir istisna ortaya çıksa bile gerçekleşecektir. Çok kullanışlı kod bloğu.
S. Brentson

2
Bu işlevi kullanarak nesnelerin bir listesini nasıl kaydedebilirim Onu kullandım ama sadece listemdeki son nesneyi
kaydediyor

1
Bu yöntem dahili veya özel alanları kaydetmez, bunu kullanabilirsiniz: github.com/mrbm2007/ObjectSaver
mrbm

153

Bir nesnenin verilerini Binary, XML veya Json'a kaydetme üzerine bir blog yazısı yazdım . Sınıflarınızı [Serializable] özniteliğiyle dekore etmeniz gerektiği konusunda haklısınız, ancak yalnızca İkili serileştirmeyi kullanıyorsanız. XML veya Json serileştirmeyi tercih edebilirsiniz. İşte bunu çeşitli formatlarda yapmak için işlevler. Daha fazla ayrıntı için blog yazıma bakın.

İkili

/// <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 binary 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 binary 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 binary 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 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 derlemesinin projenize dahil edilmesini gerektirir.

/// <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

Sen alınabilir montaj Newtonsoft.Json bir başvuru içermelidir Json.NET Nuget Paketi .

/// <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();
    }
}

Misal

// Write the contents of the variable someClass to a file.
WriteToBinaryFile<SomeClass>("C:\someClass.txt", object1);

// Read the file contents back into a variable.
SomeClass object1= ReadFromBinaryFile<SomeClass>("C:\someClass.txt");

2
İkili serileştirme kodunuzu beğendim. Ama WriteToBinaryFile üzerinde neden dosyaya eklemek isteyesiniz ki? Her durumda yeni bir dosya oluşturmak isteyeceğiniz görülüyor. Aksi takdirde, seriyi kaldırma hakkında bir sürü ekstra bilgi olacaktır.
genel kablosuz

1
@publicwireless Evet, muhtemelen haklısınız. O zamanlar pek düşünmemiştim; Sadece 3 işlevin imzalarının eşleşmesini istedim: P
deadlydog

append yöntemini kullanarak, aynı dosyadaki birçok nesneyi serileştirerek, bunların serisini nasıl kaldırırım? akıntıda nasıl ararım?
John Demetriou

1
Lütfen, ortaya çıkan verilerin derlemenin güçlü adıyla damgalandığını ve yeniden yönlendirme bağlamaları eklemeden veya söz konusu bağlamalara uymayan ortamlarda (örneğin powershell) çalıştırılmadan bunun sürümlerinde değişiklik yapılmasını önerecek olan ikili serileştiriciye yorumu ekleyin. başarısız
zaitsman

1
@JohnDemetriou Bir dosyaya birden fazla şey kaydediyorsanız, nesneleri bir tür bağlam nesnesine sarmanızı ve bu nesneyi serileştirmenizi öneririm (Nesne yöneticisinin istediğiniz parçaları ayrıştırmasına izin verin). Bellekte tutabileceğinizden daha fazla veri kaydetmeye çalışıyorsanız, dosya yerine bir nesne deposuna (nesne veritabanı) geçmek isteyebilirsiniz.
Tezra

30

Bir şeye serileştirmeniz gerekir: yani, ikili veya xml (varsayılan serileştiriciler için) seçin veya başka bir metin biçimine serileştirmek için özel serileştirme kodu yazın.

Bunu seçtikten sonra, serileştirmeniz (normalde) bir tür dosyaya yazan bir Akış olarak adlandırılır.

Öyleyse, kodunuzla, XML Serialization kullanıyor olsaydım:

var path = @"C:\Test\myserializationtest.xml";
using(FileStream fs = new FileStream(path, FileMode.Create))
{
    XmlSerializer xSer = new XmlSerializer(typeof(SomeClass));

    xSer.Serialize(fs, serializableObject);
}

Ardından seri halini kaldırmak için:

using(FileStream fs = new FileStream(path, FileMode.Open)) //double check that...
{
    XmlSerializer _xSer = new XmlSerializer(typeof(SomeClass));

    var myObject = _xSer.Deserialize(fs);
}

NOT: Bu kod derlenmemiştir, çalıştırılmak şöyle dursun - bazı hatalar olabilir. Ayrıca, bu tamamen kullanıma hazır serileştirme / seriyi kaldırma işlemini varsayar. Özel davranışa ihtiyacınız varsa, ek çalışma yapmanız gerekecektir.


10

1. Dosyadan Nesneyi Geri Yükle

Gönderen Burada iki şekilde dosyadan bir nesne serisini.

Çözüm-1: Dosyayı bir dizeye okuyun ve JSON'yi bir türe göre serileştirin

string json = File.ReadAllText(@"c:\myObj.json");
MyObject myObj = JsonConvert.DeserializeObject<MyObject>(json);

Çözüm-2: JSON'yi doğrudan bir dosyadan seriyi kaldırın

using (StreamReader file = File.OpenText(@"c:\myObj.json"))
{
    JsonSerializer serializer = new JsonSerializer();
    MyObject myObj2 = (MyObject)serializer.Deserialize(file, typeof(MyObject));
}

2. Nesneyi Dosyaya Kaydet

dan burada iki şekilde dosyaya bir nesne seri olabilir.

Çözüm-1: JSON'u bir dizeye seri hale getirin ve ardından dizeyi bir dosyaya yazın

string json = JsonConvert.SerializeObject(myObj);
File.WriteAllText(@"c:\myObj.json", json);

Çözüm-2: JSON'yi doğrudan bir dosyaya seri hale getirin

using (StreamWriter file = File.CreateText(@"c:\myObj.json"))
{
    JsonSerializer serializer = new JsonSerializer();
    serializer.Serialize(file, myObj);
}

3. Ekstra

Şunlar arasından Newtonsoft.Json indirebilirsiniz Nuget şu komutla

Install-Package Newtonsoft.Json

1

** 1. Json dizesini base64string'e dönüştürün ve bunu ikili dosyaya yazın veya ekleyin. 2. İkili dosyadan base64string'i okuyun ve BsonReader'ı kullanarak serisini kaldırın. **

 public static class BinaryJson
{
    public static string SerializeToBase64String(this object obj)
    {
        JsonSerializer jsonSerializer = new JsonSerializer();
        MemoryStream objBsonMemoryStream = new MemoryStream();
        using (BsonWriter bsonWriterObject = new BsonWriter(objBsonMemoryStream))
        {
            jsonSerializer.Serialize(bsonWriterObject, obj);
            return Convert.ToBase64String(objBsonMemoryStream.ToArray());
        }           
        //return Encoding.ASCII.GetString(objBsonMemoryStream.ToArray());
    }
    public static T DeserializeToObject<T>(this string base64String)
    {
        byte[] data = Convert.FromBase64String(base64String);
        MemoryStream ms = new MemoryStream(data);
        using (BsonReader reader = new BsonReader(ms))
        {
            JsonSerializer serializer = new JsonSerializer();
            return serializer.Deserialize<T>(reader);
        }
    }
}

1

JsonConvert'ı Newtonsoft kütüphanesinden kullanabilirsiniz. Bir nesneyi serileştirmek ve json formatında bir dosyaya yazmak için:

File.WriteAllText(filePath, JsonConvert.SerializeObject(obj));

Ve onu nesneye geri döndürmek için:

var obj = JsonConvert.DeserializeObject<ObjType>(File.ReadAllText(filePath));
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.