logo

English

이곳의 프로그래밍관련 정보와 소스는 마음대로 활용하셔도 좋습니다. 다만 쓰시기 전에 통보 정도는 해주시는 것이 예의 일것 같습니다. 질문이나 오류 수정은 siseong@gmail.com 으로 주세요. 감사합니다.

[C#] StreamReader 에서의 한글 Encoding 문제

by digipine posted Oct 29, 2017
?

Shortcut

PrevPrev Article

NextNext Article

Larger Font Smaller Font Up Down Go comment Print
?

Shortcut

PrevPrev Article

NextNext Article

Larger Font Smaller Font Up Down Go comment Print

오늘은 개발자 한 분이... ASP.NET 에서 한글이 포함된 HTML 텍스트를 로딩했는 데, 한글이 깨진다는 문제를 들고 왔습니다.

텍스트 파일의 특성상, 가볍게 다음과 같은 코드로 마무리를 지었던 것입니다.


string fileContent = null;
using ( StreamReader sr = new StreamReader( filePath ) )
{
fileContent = sr.ReadToEnd();
sr.Close();
}


저 역시, 위의 코드를 보고 너무 표준적인 코드라 ^^ 문제가 없어 보였지요.

.NET 에서는 문자열 처리를 명시적으로 지정하지 않는 한, 기본적으로 "System.Text.UTF8Encoding" 으로 처리를 합니다. 문제는 거기서 발생을 하지요.

해당 HTML 텍스트 한글 파일은 메모장에서 "ASCII" 형식으로 저장된 것이었고, 디코딩을 UTF-8 로 해버리니 당연히 깨질 수 밖에 없습니다.

한글이 포함된 ASCII 코드를 정상적으로 읽어들이기 위해서는 인코딩을 지정해야 합니다. StreamReader 의 두번째 인자에는 바로 그 인코딩 방식을 지정할 수가 있죠. 우리가 아는 것처럼 "KS_C_5601-1987" 인코딩 방식을 지정해야 합니다. 다음과 같은 코드로.


using ( StreamReader sr = new StreamReader( filePath, Encoding.GetEncoding( "ks_c_5601-1987" ) ) )
{
fileContent = sr.ReadToEnd();
sr.Close();
}


명시적인 Encoding 문자열 지정대신에, Encoding.Default 를 지정해도 됩니다. 시스템 레벨로 설정된 (제어판의 Regional Settings) code page 값이 한글 윈도우즈에서는 기본적으로 "KS_C_5601-1987" 이기 때문입니다.

하지만, 여기서 끝이 아니죠. ^^
만약 해당 파일이 utf-8 또는 unicode 로 인코딩된 텍스트 파일이라면? 당연히 위의 코드로 읽어들이게 되면 역시 한글이 깨지게 됩니다.

Unicode 또는 UTF-8 등의 텍스트 파일은 그 인코딩 방법을 표시하기 위해, 파일의 최초 2~3바이트에 BOM(byte order mark)를 표시해 둡니다. utf-8 로 인코딩된 텍스트 파일을 윈도우즈의 "메모장"으로 열어보면 그러한 표시를 생략하고 순수 텍스트만 보여주지만, 2진 파일 형식으로 볼 수 있는 hexa 에디터등을 통해서 보게 되면, 최초 2~3바이트의 내용이 인코딩에 따라서 달라지는 것을 확인할 수 있습니다.


UTF-8: EF BB BF
Unicode: FF FE


실제로, BOM 을 통한 디코딩을 지원하지 않는 Editor 로 UTF-8 인코딩된 파일을 열게 되면, 최초 3byte 를 깨진 텍스트로 출력해 주는 것을 볼 수 있습니다.

아뭏든... 그렇다면, 우리도 BOM 을 읽어서 상황에 따라 StreamReader 의 2번째 인자에 각각 해당하는 인코딩을 넣어주면 되겠지요. ^^; 아마도 C++ 이었다면 틀림없이 그렇게 해야 했을 것입니다. 하지만, 우리의 "친절한 .NET 씨"(이 표현은 Loner(
http://simpleisbest.net)에서 빌려옴) 는 그런 작업을 모두 해놓았습니다. 바로 StreamReader 의 3번째 인자에서 그러한 역할을 대신해 줍니다.


public StreamReader(..., bool detectEncodingFromByteOrderMarks);

매개변수 이름 부터 그런 태생임을 짐작하게 해줍니다. 해당 값을 true 로 전달하면 BOM 마크가 없는 - 예를 들어 ANSI 파일 - 경우에는 2번째 인자에서 지정한 Encoding 방식으로 인식해서 디코딩을 하지만, BOM 이 있으면 거기서 지정된 Encoding 방식으로 되어 있다고 인식해서 디코딩을 하게 됩니다.

그러니... 앞으로 국내에서의 .NET 개발자들은 텍스트 파일을 로딩하기 위한 표준 코드를 다음과 같이 해야 합니다.

using ( StreamReader sr = new StreamReader( filePath, Encoding.GetEncoding( "ks_c_5601-1987" ), true ) )
{
fileContent = sr.ReadToEnd();
sr.Close();
}


또는

using ( StreamReader sr = new StreamReader( filePath, Encoding.Default, true ) )
{
fileContent = sr.ReadToEnd();
sr.Close();
}


두 가지 모두, 경우에 따라서 논란의 여지가 있지만... 적어도 한글 윈도우즈에서 호스팅 된다는 보장만 된다면, "Encoding.Default" 인자가 가장 좋을 것 같네요. ^^ 

TAG •
?

List of Articles
No. Subject Author Date Views
41 [Windows] DOS 명령어 실행하고 결과 스트링 가져오는 샘플 코드 digipine 2017.11.02 12
40 VC++ UTF8 변환 관련 매크로 digipine 2017.11.02 10
39 C# 으로 구현한 화면 캡춰 클래스 1 digipine 2017.11.02 9
38 C# - 한글로된 폰트명 처리 방법 개선 (Font Name Localization) digipine 2017.11.02 2
» [C#] StreamReader 에서의 한글 Encoding 문제 digipine 2017.10.29 2
36 [API Hooking] Dll Injection 하는 방법 digipine 2017.10.29 2
35 [WIN32] 파일 핸들로 파일 명 구하기 digipine 2017.10.29 2
34 [WIN32] Process ID로 HWND 구하기 digipine 2017.10.29 2
33 MS의 Hot Fix API의 유형 연구 digipine 2017.10.29 2
32 [WIN32] 실행 중인 프로세스를 외부에서 강제로 종료, 안전한 TerminateProcess digipine 2017.10.29 2
31 [WIN32] API Hook 정리 문서 digipine 2017.10.29 3
30 [WIN32, WINCE] 디스크 용량 구하는 방법 API GetDiskFreeSpaceEx digipine 2017.10.29 2
29 [WINCE] MulDiv 함수 구현 digipine 2017.10.29 2
28 [DirectShow] 화면 원본 비율유지 digipine 2017.10.29 2
27 [VC++, WInAPI] 폴더를 통채로 지우기, 서브 폴더 포함, DeleteAllFiles digipine 2017.10.29 4
26 [Win API]프로세스 아이디와 윈도우 핸들을 이용 파일명 구하기 digipine 2017.10.29 2
25 RegEnumKeyEx 함수 사용법 digipine 2017.10.29 2
24 [WINCE] Process, Thread API 함수 사용법 digipine 2017.10.29 3
23 [WINCE] 메모리카드 상태 감시 digipine 2017.10.29 2
22 [WINCE] IAT Hooking 방법과 소스 코드 digipine 2017.10.29 3
Board Pagination Prev 1 2 3 Next
/ 3