유니코드와 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();
*/
본 웹사이트는 광고를 포함하고 있습니다. 광고 클릭에서 발생하는 수익금은 모두 웹사이트 서버의 유지 및 관리, 그리고 기술 콘텐츠 향상을 위해 쓰여집니다.