Wie speichere / stelle ich ein serialisierbares Objekt in / aus einer Datei wieder her?

94

Ich habe eine Liste von Objekten und muss diese irgendwo auf meinem Computer speichern. Ich habe einige Foren gelesen und weiß, dass das Objekt sein muss Serializable. Aber es wäre schön, wenn ich ein Beispiel bekommen könnte. Zum Beispiel, wenn ich Folgendes habe:

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

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

Aber wie kann ich object1irgendwo auf meinem Computer speichern und später abrufen?

Tono Nam
quelle
3
Hier ist ein Tutorial, das zeigt, wie man in eine Datei serialisiert switchonthecode.com/tutorials/…
Brook

Antworten:

139

Sie können Folgendes verwenden:

    /// <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
quelle
1
Nett! Obwohl string attributeXml = string.Empty;in DeSerializeObjectnie benutzt wird;)
Jimbo
3
Sie müssen die close-Methode nicht auf einem Reader in Ihrem using-Block aufrufen. Dispose () ist implizit und findet auch dann statt, wenn innerhalb des Blocks vor dem expliziten Close () eine Ausnahme ausgelöst wird. Sehr nützlicher Codeblock.
S. Brentson
2
So speichern Sie eine Liste von Objekten mit dieser Funktion Ich habe sie verwendet, aber es wird nur das letzte Objekt in meiner Liste
gespeichert
1
Diese Methode speichert keine internen oder privaten Felder. Sie können
Folgendes
147

Ich habe gerade einen Blog-Beitrag über das Speichern der Daten eines Objekts in Binary, XML oder Json geschrieben . Sie haben Recht, dass Sie Ihre Klassen mit dem Attribut [Serializable] dekorieren müssen, jedoch nur, wenn Sie die binäre Serialisierung verwenden. Möglicherweise bevorzugen Sie die Verwendung der XML- oder Json-Serialisierung. Hier sind die Funktionen, um dies in den verschiedenen Formaten zu tun. Weitere Informationen finden Sie in meinem Blogbeitrag.

Binär

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

Erfordert, dass die System.Xml-Assembly in Ihr Projekt aufgenommen wird.

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

Sie müssen einen Verweis auf die Newtonsoft.Json-Assembly hinzufügen, der im Json.NET NuGet-Paket erhältlich ist .

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

Beispiel

// 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");
tödlicher Hund
quelle
2
Ich mag Ihren binären Serialisierungscode. Aber warum sollten Sie auf WriteToBinaryFile jemals an die Datei anhängen wollen? Anscheinend möchten Sie in jedem Fall eine neue Datei erstellen. Andernfalls würde es eine ganze Reihe zusätzlicher Informationen zur Deserialisierung geben.
öffentliche drahtlose
1
@publicwireless Ja, du hast wahrscheinlich recht. Ich habe damals nicht viel darüber nachgedacht; Ich wollte nur, dass die Signaturen der 3 Funktionen übereinstimmen: P
tödlicher Hund
Wie deserialisiere ich mithilfe der Append-Methode viele Objekte in derselben Datei? Wie suche ich im Stream?
John Demetriou
1
Bitte fügen Sie den Kommentar zum binären Serializer hinzu, der die Benutzer darauf hinweist, dass die resultierenden Daten mit dem starken Namen der Assembly versehen sind, und Änderungen an Versionen davon vornehmen, ohne Umleitungsbindungen hinzuzufügen oder in Umgebungen auszuführen, die diese Bindungen nicht berücksichtigen (z. B. Powershell) fail
zaitsman
1
@JohnDemetriou Wenn Sie mehrere Dinge in einer Datei speichern, würde ich empfehlen, die Objekte in eine Form von Kontextobjekt zu verpacken und dieses Objekt zu serialisieren (Lassen Sie den Objektmanager die gewünschten Teile analysieren). Wenn Sie versuchen, mehr Daten zu speichern, als Sie im Speicher speichern können, möchten Sie möglicherweise zu einem Objektspeicher (Objektdatenbank) anstelle einer Datei wechseln.
Tezra
30

Sie müssen zu etwas serialisieren: Wählen Sie Binär oder XML (für Standard-Serialisierer) oder schreiben Sie einen benutzerdefinierten Serialisierungscode, um in eine andere Textform zu serialisieren.

Sobald Sie dies ausgewählt haben, ruft Ihre Serialisierung (normalerweise) einen Stream auf, der in eine Art Datei schreibt.

Also, mit Ihrem Code, wenn ich XML-Serialisierung verwenden würde:

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

    xSer.Serialize(fs, serializableObject);
}

Dann, um zu deserialisieren:

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

    var myObject = _xSer.Deserialize(fs);
}

HINWEIS: Dieser Code wurde nicht kompiliert, geschweige denn ausgeführt. Möglicherweise liegen einige Fehler vor. Dies setzt auch eine sofort einsatzbereite Serialisierung / Deserialisierung voraus. Wenn Sie ein benutzerdefiniertes Verhalten benötigen, müssen Sie zusätzliche Arbeiten ausführen.

AllenG
quelle
10

1. Objekt aus Datei wiederherstellen

Von hier aus können Sie ein Objekt auf zwei Arten aus einer Datei deserialisieren.

Lösung 1: Lesen Sie die Datei in eine Zeichenfolge und deserialisieren Sie JSON in einen Typ

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

Lösung 2: Deserialisieren Sie JSON direkt aus einer Datei

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

2. Objekt in Datei speichern

von hier aus können Sie ein Objekt auf zwei Arten in eine Datei serialisieren.

Lösung 1: Serialisieren Sie JSON in eine Zeichenfolge und schreiben Sie dann eine Zeichenfolge in eine Datei

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

Lösung 2: Serialisieren Sie JSON direkt in eine Datei

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

3. Extra

Sie können Newtonsoft.Json von NuGet herunterladen, indem Sie den folgenden Befehl ausführen

Install-Package Newtonsoft.Json
Emdadul Sawon
quelle
1

** 1. Konvertieren Sie die JSON-Zeichenfolge in base64string und schreiben Sie sie oder hängen Sie sie an eine Binärdatei an. 2. Lesen Sie base64string aus der Binärdatei und deserialisieren Sie mit 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);
        }
    }
}
Gast
quelle
0

Sie können JsonConvert aus der Newtonsoft-Bibliothek verwenden. So serialisieren Sie ein Objekt und schreiben in eine Datei im JSON-Format:

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

Und um es wieder in ein Objekt zu deserialisieren:

var obj = JsonConvert.DeserializeObject<ObjType>(File.ReadAllText(filePath));
Ozanmut
quelle