직렬화: 객체의 상태(객체의 필드에 저장된 값들을 의미)를 메모리나 영구 저장 장치에 저장이 가능한 0과 1의 순서로 바꾸는 것을 의미합니다.
C#에서 객체를 직렬화하는 방법은 아주아주 간단합니다.
그저 [Serializable] 애트리뷰트를 클래스 선언부 앞에 붙여주면 이 클래스는 메모리나 영구 저장 장치에 저장이 가능한 형식이 됩니다.
[Serializable]
class MyClass
{
...
}
이렇게 선언된 형식은 다음과 같이 Stream 클래스와 BinaryFormatter를 이용해서 간단히 저장할 수 있습니다.
//a.dat 파일을 생성
Stream ws = new FileStream("a.dat", FileMode.Create);
//BinaryFormatter은 System.Runtime.Serialization.Formatters.Binary 네임스페이스에
//속한 클래스로 객체를 직렬화 하거나 역직렬화 하는 것
BinaryFormatter serializer = new BinaryFormatter();
//obj의 필드에 값 저장
MyClass obj = new MyClass();
//직렬화
serializer.Serialize(ws, nc);
//파일 닫기
ws.Close();
직렬화하는 코드는 위와 같습니다.
이제 역직렬화 하는 코드도 같이 보겠습니다.
//a.dat 파일을 열기
Stream rs = new FileStream("a.dat", FileMode.Open);
BinaryFormatter deserializer = new BinaryFormatter();
//obj의 필드에 값 저장
MyClass obj = new MyClass();
//역직렬화
nc2 = (NameCard)deserializer.Deserialize(rs);
//파일닫기
rs.Close();
클래스 안에 어떤 필드들이 어떻게 선언되어 있는지 고민할 필요가 없습니다.
좋습니다.
직렬화하고 싶지 않은 필드가 있다면 그 필드만 [NonSerialized] 애트리뷰트로 수식해 주면 됩니다.
[Serializable]
class MyClass
{
public int MField1;
public int MField2;
//MField3를 제외한 나머지 필드들만 직렬화 됩니다.
[NonSerialized] public int MField3;
public int MField4;
}
복합 데이터 형식을 직렬화할 때 주의할 점
class NonserializableClass
{
public int MField;
}
[Serializable]
class MyClass
{
public int MField1;
public int MField2;
//!오류!
public NonserializableClass MField3;
public int MField4;
}
위 코드에서 NonserializableClass는 Serializable 하지 않으므로 직렬화를 수행할 때 오류가 발생합니다.
해결할 방법은 두가지입니다.
- NonserializableClass 클래스를 Serializable 애트리뷰트로 수식하기
- MField3을 Nonserializable 애트리뷰트로 수식하기
그러면 컬렉션까지 써서 전체 예제를 보겠습니다.
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
namespace SerializingCollection
{
[Serializable]
class NameCard
{
public NameCard(string Name, string Phone, int Age)
{
this.Name = Name;
this.Phone = Phone;
this.Age = Age;
}
public string Name;
//전화번호는 직렬화 안하기
[NonSerialized] public string Phone;
public int Age;
}
class MainApp
{
static void Main(string[] args)
{
Stream ws = new FileStream("a.dat", FileMode.Create);
BinaryFormatter serializer = new BinaryFormatter();
List<NameCard> list = new List<NameCard>();
list.Add(new NameCard("박상현", "010-123-4567", 33));
list.Add(new NameCard("김연아", "010-323-1111", 22));
list.Add(new NameCard("장미란", "010-555-5555", 26));
serializer.Serialize(ws, list);
ws.Close();
Stream rs = new FileStream("a.dat", FileMode.Open);
BinaryFormatter deserializer = new BinaryFormatter();
List<NameCard> list2;
list2 = (List<NameCard>)deserializer.Deserialize(rs);
rs.Close();
foreach (NameCard nc in list2)
{
Console.WriteLine(
$"Name: {nc.Name}, Phone: {nc.Phone}, Age: {nc.Age}");
}
}
}
}

'C# 프로그래밍' 카테고리의 다른 글
[C#] 스레드 사용법(1) (0) | 2023.03.13 |
---|---|
프로세스와 스레드에 대한 이론 정리글(1) (feat. chat gpt) (0) | 2023.03.09 |
"=>" 연산자가 람다식 말고 쓰이는 곳 "식 본문 멤버" (0) | 2023.03.06 |
[C#] 문 형식의 람다식 (0) | 2023.03.06 |
[C#] 익명 메소드와 람다식 (0) | 2023.02.28 |