C#
유니코드와 BOM

일련의 텍스트 데이타를 16비트 유니코드로 저장할 때, Endian 에 따라 바이트 위치가 변경될 수 있다. 즉, Big-Endian의 경우, MSB (most significant byte) 바이트를 먼저 쓰는 반면, Little-Endian의 경우, LSB (least significant byte) 바이트를 먼저 쓰게 된다. 예를 들어, 한글 "가"의 유니코드 포인트는 U+AC00 로서 Big-Endian의 경우 "AC 00" (낮은 메모리에서 높은 메모리 방향) 와 같이 저장되지만, Little-Endian의 경우 "00 AC" 와 같이 저장된다.

텍스트 파일에 이러한 유니코드 데이타를 저장할 때, 어떤 Endian이 사용되었는지를 나타내기 위해 BOM (byte order mark) 이라는 표시를 사용하게 되었다. 즉, Big-Endian의 경우 파일의 첫부분에 "FE FF" 를 사용하였고, Little-Endian의 경우 "FF FE" 라는 BOM 마크를 표시한 것이다. (BOM은 텍스트 파일 이외에 텍스트 스트림 등에 나타날 수 있으며, Optional로서 항상 있는 것은 아니다)




UTF인코딩과 BOM

예전 16비트 유니코드는 UCS-2 인코딩을 사용하다 이를 좀 더 확장한 UTF-16 인코딩을 사용하고 있다 (C#에서 Unicode Encoding이라 함은 UTF-16 인코딩을 의미한다). UTF-16 인코딩은 모든 문자에 대해 16비트를 사용하므로 알파벳과 같은 8비트로 전송할 수 있는 문자들에는 비효율적인 측면이 있다 UTF-8 인코딩은 문자의 종류에 따라 1바이트부터 4바이트까지 다양하게 인코딩할 수 있는데, ASCII 문자는 1바이트로 표현하기 때문에 ASCII 데이타가 주를 이루지만 다른 문자들도 함께 있어야 하는 상황에 유용하다. UTF 인코딩에는 UTF-8, UTF-16 이외에 UTF-32, UTF-7 등이 있다.\n\n 텍스트 파일 혹은 텍스트 스트림에서는 이러한 UTF 인코딩의 종류에 따라 서로 다른 BOM (byte order mark)을 사용하고 있다. 아래는 각 인코딩에서 사용하는 BOM을 표시한 것이다.

인코딩 방식 BOM
Unicode (Big-Endian) FE FF
Unicode (Little-Endian) FF FE
UTF8 EF BB BF
UTF-32 (Big-Endian) 00 00 FE FF
UTF-32 (Little-Endian) FF FE 00 00

텍스트 파일에서의 인코딩 사용

C# 코드에서 텍스트 파일을 생성할 때, 특정한 인코딩을 지정할 수 있다. 특히, 텍스트가 ASCII 이외의 국제 문자의 경우 UTF 인코딩을 지정해 주는 것이 좋다. 예를 들어, 한글 문자열이 있는 텍스트 파일을 .csv 파일로 저장하고 이를 영문 OS에서 Excel 로 읽으면, 한글이 깨져 보이게 된다. (동일한 .csv 파일을 NotePad로 읽으면 한글을 읽을 수 있다). 따라서, 이러한 경우는 인코딩을 명시하는 것이 필요하다.

아래 예제에서 StreamWriter 객체를 생성할 때 생성자에서 Encoding.UTF8 과 같이 인코딩 방식을 지정하였다. 이렇게 인코딩을 지정하면, 텍스트 파일의 처음 BOM 부분이 자동으로 추가되게 된다. 즉, UTF8의 경우 파일 처음 부분에 0xEF 0xBB 0xBF 등 3개의 바이트가 BOM으로 추가된다.

아래 예제는 다양한 인코딩 방식으로 동일한 데이타를 저장한 예이다. 이 코드를 실행하여 생성된 텍스트 파일을 Hex Editor로 살펴보면 아래 그림과 같이 BOM이 자동 추가됨을 알 수 있다.


예제

string data = "A";
//string data = "가";

StreamWriter wr = new StreamWriter("default.csv");
wr.Write(data);
wr.Close();

wr = new StreamWriter("utf8.csv", false, Encoding.UTF8);
wr.Write(data);
wr.Close();

wr = new StreamWriter("unicode.csv", false, Encoding.Unicode);
wr.Write(data);
wr.Close();

wr = new StreamWriter("utf32.csv", false, Encoding.UTF32);
wr.Write(data);
wr.Close();

/*
wr = new StreamWriter("utf7.csv", false, Encoding.UTF7);
wr.Write(data);
wr.Close();

wr = new StreamWriter("cp949.csv", false, Encoding.GetEncoding(949));
wr.Write(data);
wr.Close();
*/





본 웹사이트는 광고를 포함하고 있습니다. 광고 클릭에서 발생하는 수익금은 모두 웹사이트 서버의 유지 및 관리, 그리고 기술 콘텐츠 향상을 위해 쓰여집니다.