Bagaimana cara menyimpan / mengembalikan objek berseri ke / dari file?

95

Saya memiliki daftar objek dan saya perlu menyimpannya di suatu tempat di komputer saya. Saya telah membaca beberapa forum dan saya tahu bahwa objeknya haruslah Serializable. Tapi alangkah baiknya jika saya bisa mendapatkan contoh. Misalnya jika saya memiliki yang berikut ini:

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

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

Tapi bagaimana saya bisa menyimpan object1di suatu tempat di komputer saya dan mengambilnya nanti?

Tono Nam
sumber
3
Berikut adalah tutorial yang menunjukkan cara membuat serial ke file switchonthecode.com/tutorials/…
Brook

Jawaban:

144

Anda dapat menggunakan berikut ini:

    /// <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;
    }
Alex Mendez
sumber
1
Bagus! Meskipun string attributeXml = string.Empty;di DeSerializeObjecttidak pernah digunakan;)
Jimbo
3
Tidak perlu memanggil metode tutup pada pembaca dalam blok penggunaan Anda. Dispose () adalah implisit dan akan berlangsung bahkan jika pengecualian dimunculkan dalam blok sebelum Close () eksplisit. Blok kode yang sangat berguna.
S. Brentson
2
Bagaimana cara menyimpan daftar objek menggunakan fungsi ini Saya telah menggunakannya tetapi hanya menyimpan objek terakhir dalam daftar saya
Decoder94
1
Metode ini tidak akan menyimpan bidang internal atau pribadi, Anda dapat menggunakan ini: github.com/mrbm2007/ObjectSaver
mrbm
152

Saya baru saja menulis posting blog tentang menyimpan data objek ke Biner, XML, atau Json . Anda benar bahwa Anda harus mendekorasi kelas Anda dengan atribut [Serializable], tetapi hanya jika Anda menggunakan serialisasi Biner. Anda mungkin lebih suka menggunakan serialisasi XML atau Json. Berikut fungsi untuk melakukannya dalam berbagai format. Lihat posting blog saya untuk lebih jelasnya.

Biner

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

Membutuhkan perakitan System.Xml untuk disertakan dalam proyek Anda.

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

Anda harus menyertakan referensi ke perakitan Newtonsoft.Json, yang dapat diperoleh dari Paket NuGet Json.NET .

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

Contoh

// 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");
anjing mematikan
sumber
2
Saya suka kode serialisasi Biner Anda. Tetapi pada WriteToBinaryFile mengapa Anda ingin menambahkan ke file? Sepertinya Anda ingin membuat file baru dalam semua kasus. Jika tidak, akan ada sejumlah besar informasi tambahan tentang deserialization.
nirkabel publik
1
@publicwireless Ya, Anda mungkin benar. Saya tidak terlalu memikirkannya saat itu; Saya hanya ingin tanda tangan dari 3 fungsi yang cocok: P
deadlydog
menggunakan metode append, membuat serialisasi banyak objek dalam file yang sama, bagaimana cara menghapusnya? bagaimana cara mencari di arus?
John Demetriou
1
Harap tambahkan komentar ke serializer biner yang akan memberi tahu orang-orang bahwa data yang dihasilkan dicap dengan nama kuat dari assembly dan perubahan versi ini tanpa menambahkan pengikatan pengalihan atau berjalan di lingkungan yang tidak menghormati pengikatan tersebut (misalnya, PowerShell) akan gagal
zaitsman
1
@JohnDemetriou Jika menyimpan banyak hal ke file, saya akan merekomendasikan membungkus objek dalam beberapa bentuk objek konteks dan membuat serial objek itu (Biarkan pengelola objek mengurai bagian yang Anda inginkan). Jika Anda mencoba untuk menyimpan lebih banyak data daripada yang bisa Anda simpan di memori, Anda mungkin ingin beralih ke penyimpanan objek (database objek) daripada file.
Tezra
30

Anda harus membuat serial ke sesuatu: yaitu, memilih biner, atau xml (untuk serializers default) atau menulis kode serialisasi khusus untuk membuat serial ke beberapa bentuk teks lainnya.

Setelah Anda memilihnya, serialisasi Anda (biasanya) akan memanggil Stream yang menulis ke beberapa jenis file.

Jadi, dengan kode Anda, jika saya menggunakan Serialisasi XML:

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

    xSer.Serialize(fs, serializableObject);
}

Kemudian, untuk melakukan deserialisasi:

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

    var myObject = _xSer.Deserialize(fs);
}

CATATAN: Kode ini belum dikompilasi, apalagi dijalankan- mungkin ada beberapa kesalahan. Juga, ini mengasumsikan serialisasi / deserialisasi benar-benar out-of-the-box. Jika Anda membutuhkan perilaku khusus, Anda harus melakukan pekerjaan tambahan.

AllenG
sumber
10

1. Pulihkan Objek Dari File

Dari sini Anda dapat melakukan deserialisasi objek dari file dengan dua cara.

Solusi-1: Baca file menjadi string dan deserialisasi JSON ke suatu jenis

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

Solusi-2: Deserialisasi JSON langsung dari file

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

2. Simpan Objek Ke File

dari sini Anda dapat membuat serial objek ke file dengan dua cara.

Solusi-1: Buat serial JSON menjadi string dan kemudian tulis string ke file

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

Solusi-2: Serialisasi JSON langsung ke file

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

3. Ekstra

Anda dapat mengunduh Newtonsoft.Json dari NuGet dengan mengikuti perintah

Install-Package Newtonsoft.Json
Emdadul Sawon
sumber
1

** 1. Ubah string json menjadi base64string dan Tulis atau tambahkan ke file biner. 2. Baca base64string dari file biner dan deserialisasi menggunakan BsonReader. **

 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);
        }
    }
}
tamu
sumber
1

Anda dapat menggunakan JsonConvert dari perpustakaan Newtonsoft. Untuk membuat serial objek dan menulis ke file dalam format json:

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

Dan untuk menghilangkannya kembali menjadi objek:

var obj = JsonConvert.DeserializeObject<ObjType>(File.ReadAllText(filePath));
ozanmut
sumber