'2018/06'에 해당되는 글 3건

Programming/.NET

C#에서는 문자열이나 정수와 같은 타입의 데이터를 byte배열로 변환하는 직렬화를 수행할 수 있으며 물론 그 반대로 가능합니다. 그렇다면 기본 데이터타입이 아닌 직접 만든 클래스와 같은 요소는 어떻게 직렬화를 수행할 수 있을까?

 

System.Runtime.Serialization.Formatters.Binary.BinaryFormatter가 그 답이 될 수 있습니다.

 

예를 들어 아래와 같은 클래스가 있습니다.

 

class Employee
{
    public Employee(string name, string department, int level)
    {
        Name = name;
        Department = department;
        Level = level;
    }

    public string Name
    {
        get;
        set;
    }

    public string Department
    {
        get;
        set;
    }

    public int Level
    {
        get;
        set;
    }
}

 

이 클래스를 직렬화하기 위해서는 우선 [Serializable] 이라는 특성을 클래스에 추가해 해당 클래스가 직렬화가능함을 알려줘야 합니다.

 

[Serializable]
class Employee

 

그리고 직렬화를 수행하려는 클래스에 대해 필요한 적절한 작업을 수행한 뒤

 

Employee e1 = new test.Employee("홍길동", "관리부", 4);

 

BinaryFormatter를 통해 MemoryStream으로 다음과 같이 직렬화를 수행합니다.

 

System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bf = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();

MemoryStream ms = new MemoryStream();
bf.Serialize(ms, e1);

 

대부분 네트워크를 통해 다른 시스템으로 개체전체를 전송하고자 할때 직렬화를 많이 수행하는데 문제는 직렬화방식이 내부에 감춰져 있어서 .NET이 아닌 다른 플렛폼에서는 역직렬화가 힘들다는 단점이 있습니다.

 

Employee e1 = new test.Employee("홍길동", "관리부", 4);

System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bf = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();

MemoryStream ms = new MemoryStream();
bf.Serialize(ms, e1);

ms.Position = 0;

Employee e2 = (Employee)bf.Deserialize(ms);

Console.WriteLine(e2.Name);

 

역직렬화는 간단합니다. BinaryFormatter의 Deserialize메서드를 호출해 Stream으로 읽기만 하면 됩니다. 물론 이 방법은 타 플렛폼과는 맞추기 힘든 부분이 있지만 같은 .NET환경이라면 비교적 빠르고 간단히 처리할 수 있습니다.

 

BinaryFormatter는 주어진 요소를 Binary로 직렬화하지만 System.Xml.Serialization.XmlSerializer는 문자열형태(기본 UTF8로 인코딩)로 직렬화를 수행합니다. 그런데 이름에서도 알 수 있듯이 그 문자열 포멧 형식이 XML입니다. 다만 XmlSerializer를 사용하려면 클래스를 다음과 같이 바꿔야 합니다.

 

public class Employee
{
    public Employee()
    { }
    public Employee(string name, string department, int level)
    {
        Name = name;
        Department = department;
        Level = level;
    }

    public string Name
    {
        get;
        set;
    }

    public string Department
    {
        get;
        set;
    }

    public int Level
    {
        get;
        set;
    }
}

 

먼저 클래스에 public 접근제한자가 있어야 하며 클래스안에 기본생성자를 포함해야 합니다. 하지만 이전에 추가했던 [Serializable]특성은 필요하지 않습니다.

 

Employee e1 = new test.Employee("홍길동", "관리부", 4);

System.Xml.Serialization.XmlSerializer xs = new System.Xml.Serialization.XmlSerializer(typeof(Employee));

MemoryStream ms = new MemoryStream();
xs.Serialize(ms, e1);

ms.Position = 0;

Employee e2 = (Employee)xs.Deserialize(ms);

Console.WriteLine(e2.Name);

 

BinaryFormatter와 클래스명만 다를뿐 사용법의 거의 똑같습니다. 차이라면 클래스를 통해 개체를 생성하는 부분에서는 XML스키마 작성을 위해 직렬화하려는 요소의 타입을 명시해야 한다는 것입니다.

 

XmlSerializer는 BinaryFormatter보다는 성능이 떨어지지만 XML이라는 표준포멧으로 직렬화를 수행하기에 타 플렛폼과의 호환성을 확보할 수 있다는 장점이 있습니다. 단, 직렬화되는 요소는 public제한자가 있는 필드만 가능합니다.

 

.NET 아닌 타 플렛폼입장에서 BinaryFormatter은 Binary변환으로 빠르게 처리될 수 있기는 하나 호환성에 문제가 생길 수 있고 XmlSerializer는 다소 긴 XML데이터를 생성하기는 하지만 XML포멧으로 인해 호환성문제는 해결될 수 있습니다. 각각 장단점이 존재하는데 이 둘의 장점만을 결합한 것이 바로 System.Runtime.Serialization.Json.DataContractJsonSerializer입니다. DataContractJsonSerializer는 문자열로 직렬화를 수행하기는 하지만 json포멧이기에 XML보다 훨씬 적은 데이터용량을 가질 수 있고 포멧또한 타 플렛폼에서 많이 다루는 것이므로 호환성도 확보할 수 있습니다.

 

Employee e1 = new test.Employee("홍길동", "관리부", 4);

System.Runtime.Serialization.Json.DataContractJsonSerializer dc = new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(Employee));

MemoryStream ms = new MemoryStream();
dc.WriteObject(ms, e1);

ms.Position = 0;

Employee e2 = (Employee)dc.ReadObject(ms);

Console.WriteLine(e2.Name);

 

DataContractJsonSerializer에서 직렬화는 WriteObject()로 역직렬화는 ReadObject()메서드로 처리합니다.

'Programming > .NET' 카테고리의 다른 글

[ASP.NET MVC] 헬퍼메서드(Helper Method)  (0) 2018.07.18
[C#] extern  (0) 2018.07.03
[C#] BinaryFormatter / XmlSerializer / DataContractJsonSerializer  (0) 2018.06.26
[C#] Encoding / BitConverter  (0) 2018.06.19
[C#] fixed  (0) 2018.06.13
[C#] DateTime  (0) 2018.05.29
0 0
Programming/.NET

컴퓨터는 내부적으로 데이터를 숫자로 처리합니다. A, B, C와 같은 문자도 마찬가지입니다. 그럼 시스템은 내부적으로 문자를 처리하기 위해 숫자로 표현해야 하는데 이 과정을 인코딩(Encoding)이라고 합니다.

 

다만 특정 문자를 표현하기 위해 내부적으로 문자를 어떤 숫자로 처리해야 하는가가 정해져야 하며 이를 정리한 코드체계중 대표적으로 ASCII코드가 있습니다. ASCII코드는 A를 65, B를 66... 으로 표현합니다. 하지만 ASCII코드는 7bit를 기반으로 하기에 영문자나 숫자, 일부특수문자만을 표현할 수 있을뿐 한글, 한자, 일어와 같은 문자는 표현할 수 있는 방법이 없습니다. 그래서 대한민국은 한글표현을 위해 EUC-KR, CP949, KS_C_5601-1987등의 인코딩방식을 만들게 되고 다른 나라들도 자국의 언어를 위해 별도의 인코딩방식을 마련해 뒀습니다.

 

이처럼 문자를 숫자로 처리하는 인코딩방식이 너무 많이 늘어나자 근래에는 유니코드라는 산업표준으로 문자를 인코딩하는 추세입니다.(부호화 방식에 따라 UTF-7, UTF-8, UTF-16, UTF-32등으로 나뉘어짐)

 

만약 .NET환경에서 다른 시스템이나 폴렛폼에서 다루고자 하는 인코딩방식에 맞추려고 할때 System.Text.Encoding을 사용하면 이러한 작업을 좀더 쉽게 구현할 수 있습니다.

 

예를 들어 타 시스템에서 문자를 UTF-8방식으로 사용한다면 아래와 같이 처리할 수 있을 것입니다.

 

string sample = "hello world!";
byte[] b = Encoding.UTF8.GetBytes(sample); //타 시스템으로 전송하기 위한 처리

 

sample = Encoding.UTF8.GetString(b); //타 시스템에서 전달받은 문자를 처리
Console.WriteLine(sample);

 

참고로 문자열을 제외한 다른 타입은 인코딩방식이 고정되어 있습니다. 그래서 이런 경우에는 특별히 System.BitConverter를 사용할 수 있습니다.

 

byte[] b = BitConverter.GetBytes(100);
int i = BitConverter.ToInt16(b, 0);

Console.WriteLine(i);

 

'Programming > .NET' 카테고리의 다른 글

[C#] extern  (0) 2018.07.03
[C#] BinaryFormatter / XmlSerializer / DataContractJsonSerializer  (0) 2018.06.26
[C#] Encoding / BitConverter  (0) 2018.06.19
[C#] fixed  (0) 2018.06.13
[C#] DateTime  (0) 2018.05.29
[C#] 생성자와 소멸자  (0) 2018.05.23
0 0
Programming/.NET

unsafe 영역안에서 포이터를 사용하는건 스택으로 데이터를 저장하는 값형식의 변수에서만 가능합니다. 참조형식의 변수에서 포인터를 사용할 수 없는 이유는 참조형식의 데이터는 힙에 할당되고 힙은 가비지 컬렉터에 의해 위치가 바뀔 수 있기 때문입니다. 결국 참조형식의 주소를 갖고 있던 포인터는 언제라도 전혀 엉뚱한 곳을 가리킬 수 있기 때문입니다.

 

fixed는 힙에 할당된 참조 형식의 인스턴스를 가비지 컬렉터가 건드리지 못하게 하여 위에서 말한 문제를 해결할 수 있도록 합니다.

 

static void Main()
{
    unsafe {
        string s = "abcdefg";

        fixed (char* c = s.ToCharArray()) {
        for (int i = 0; i < s.Length; i++)
            Console.WriteLine(*(c + i));
        }
}

 

string 형은 참조형으로 값을 힙에 할당합니다. 이 string형의 시작주소를 포인터 c에 할당할때 fixed를 사용하므로서 string형인 s 인스턴스의 힙주소는 고정될 것입니다.

'Programming > .NET' 카테고리의 다른 글

[C#] BinaryFormatter / XmlSerializer / DataContractJsonSerializer  (0) 2018.06.26
[C#] Encoding / BitConverter  (0) 2018.06.19
[C#] fixed  (0) 2018.06.13
[C#] DateTime  (0) 2018.05.29
[C#] 생성자와 소멸자  (0) 2018.05.23
[C#] 개체의 생성과 해제  (0) 2018.05.15
0 0
1
블로그 이미지

클리엘