직렬화 가능한 객체를 파일로 /에서 저장 / 복원하는 방법은 무엇입니까?


94

개체 목록이 있고 컴퓨터 어딘가에 저장해야합니다. 일부 포럼을 읽었으며 객체가이어야한다는 것을 알고 있습니다 Serializable. 그러나 내가 예를 얻을 수 있다면 좋을 것입니다. 예를 들어 다음과 같은 경우 :

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

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

하지만 object1내 컴퓨터 어딘가에 저장 하고 나중에 검색하려면 어떻게해야합니까?


답변:


142

다음을 사용할 수 있습니다.

    /// <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
좋은! 하지만 string attributeXml = string.Empty;의는 DeSerializeObject) 사용되지 않습니다
짐보

3
using 블록 내의 리더에서 close 메서드를 호출 할 필요가 없습니다. Dispose ()는 암시 적이며 명시 적 Close () 전에 블록 내에서 예외가 발생하더라도 발생합니다. 매우 유용한 코드 블록.
S. Brentson

2
이 기능을 사용하여 개체 목록을 저장하는 방법 나는 그것을 사용했지만 내 목록의 마지막 개체 만 저장합니다
Decoder94

1
이 방법은 내부 또는 개인 필드를 저장하지 않습니다. 다음을 사용할 수 있습니다. github.com/mrbm2007/ObjectSaver
mrbm 2017

152

객체의 데이터를 Binary, XML 또는 Json에 저장하는 것에 대한 블로그 게시물을 방금 작성 했습니다 . 이진 직렬화를 사용하는 경우에만 [Serializable] 속성으로 클래스를 장식해야한다는 것이 맞습니다. 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 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 어셈블리를 포함해야합니다.

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

Json.NET NuGet Package 에서 얻을 수있는 Newtonsoft.Json 어셈블리에 대한 참조를 포함해야합니다 .

/// <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 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
바이너리 직렬화 코드가 마음에 듭니다. 그러나 WriteToBinaryFile에서 왜 파일에 추가하고 싶습니까? 모든 경우에 새 파일을 만들고 싶은 것 같습니다. 그렇지 않으면 역 직렬화에 대한 많은 추가 정보가있을 것입니다.
공용 무선

1
@publicwireless 네, 아마 맞습니다. 나는 그 당시에 그것에 대해 많이 생각하지 않았습니다. 난 그냥 일치하는 3 개 함수의 서명을 원 : P
deadlydog

append 메소드를 사용하여 동일한 파일에서 많은 객체를 직렬화하는 경우 어떻게 deserialize합니까? 스트림에서 어떻게 찾나요?
John Demetriou

1
이진 직렬 변환기에 주석을 추가하여 결과 데이터가 어셈블리의 강력한 이름으로 스탬프 처리되고 리디렉션 바인딩을 추가하지 않고이 버전을 변경하거나 해당 바인딩 (예 : powershell)을 따르지 않는 환경에서 실행된다는 사실을 사람들에게 알릴 수 있습니다. 실패
zaitsman

1
@JohnDemetriou 파일에 여러 항목을 저장하는 경우 컨텍스트 개체 형식으로 개체를 래핑하고 해당 개체를 직렬화하는 것이 좋습니다 (개체 관리자가 원하는 부분을 구문 분석하도록 함). 메모리에 저장할 수있는 것보다 더 많은 데이터를 저장하려는 경우 파일 대신 객체 저장소 (객체 데이터베이스)로 전환 할 수 있습니다.
Tezra 2017-06-15

30

즉, 바이너리 또는 xml (기본 직렬 변환기의 경우)을 선택하거나 사용자 지정 직렬화 코드를 작성하여 다른 텍스트 형식으로 직렬화해야합니다.

일단 그것을 선택하면 직렬화는 (일반적으로) 일종의 파일에 쓰는 Stream을 호출합니다.

따라서 코드와 함께 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);
}

그런 다음 역 직렬화하려면 다음을 수행하십시오.

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

    var myObject = _xSer.Deserialize(fs);
}

참고 :이 코드는 컴파일되지 않았으며 실행은 말할 것도 없습니다. 오류가있을 수 있습니다. 또한 이것은 완전히 즉시 사용 가능한 직렬화 / 역 직렬화를 가정합니다. 사용자 지정 동작이 필요한 경우 추가 작업을 수행해야합니다.


10

1. 파일에서 개체 복원

에서 여기에 두 가지 방법으로 파일에서 개체를 직렬화 할 수 있습니다.

솔루션 -1 : 파일을 문자열로 읽고 JSON을 유형으로 역 직렬화

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

솔루션 -2 : 파일에서 직접 JSON 역 직렬화

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

2. 파일에 개체 저장

에서 여기 두 가지 방법으로 파일 객체를 직렬화 할 수 있습니다.

해결 방법 -1 : JSON을 문자열로 직렬화 한 다음 파일에 문자열 쓰기

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

해결 방법 -2 : JSON을 파일로 직접 직렬화

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

3. 추가

다음 명령을 사용 하여 NuGet 에서 Newtonsoft.Json을 다운로드 할 수 있습니다.

Install-Package Newtonsoft.Json

1

**1. json 문자열을 base64string으로 변환하고 이진 파일에 쓰거나 추가합니다. 2. 바이너리 파일에서 base64string을 읽고 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);
        }
    }
}

0

Newtonsoft 라이브러리에서 JsonConvert를 사용할 수 있습니다. 객체를 직렬화하고 json 형식으로 파일에 쓰려면 :

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

그리고 그것을 다시 객체로 역 직렬화하려면 :

var obj = JsonConvert.DeserializeObject<ObjType>(File.ReadAllText(filePath));
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.