성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] VT sequences to "CONOUT$" vs. STD_O...
[정성태] NetCoreDbg is a managed code debugg...
[정성태] Evaluating tail call elimination in...
[정성태] What’s new in System.Text.Json in ....
[정성태] What's new in .NET 9: Cryptography ...
[정성태] 아... 제시해 주신 "https://akrzemi1.wordp...
[정성태] 다시 질문을 정리할 필요가 있을 것 같습니다. 제가 본문에...
[이승준] 완전히 잘못 짚었습니다. 댓글 지우고 싶네요. 검색을 해보...
[정성태] 우선 답글 감사합니다. ^^ 그런데, 사실 저 예제는 (g...
[이승준] 수정이 안되어서... byteArray는 BYTE* 타입입니다...
글쓰기
제목
이름
암호
전자우편
HTML
홈페이지
유형
제니퍼 .NET
닷넷
COM 개체 관련
스크립트
VC++
VS.NET IDE
Windows
Team Foundation Server
디버깅 기술
오류 유형
개발 환경 구성
웹
기타
Linux
Java
DDK
Math
Phone
Graphics
사물인터넷
부모글 보이기/감추기
내용
<div style='display: inline'> <h1 style='font-family: Malgun Gothic, Consolas; font-size: 20pt; color: #006699; text-align: center; font-weight: bold'>C# - 유니코드 한글 문자열을 ks_c_5601-1987로 변환하는 방법</h1> <p> 아래와 같은 질문이 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > dot net micro framework 에서 encoding 변환 ; <a target='tab' href='http://social.msdn.microsoft.com/Forums/ko-KR/847b2a69-b53f-43fa-8455-439f11a985c2/dot-net-micro-framework-encoding-?forum=dotnetko&amp;prof=required'>http://social.msdn.microsoft.com/Forums/ko-KR/847b2a69-b53f-43fa-8455-439f11a985c2/dot-net-micro-framework-encoding-?forum=dotnetko&prof=required</a> </pre> <br /> 질문의 내용을 요약하면, ".NET Micro Framework"는 System.Text.Encoding.UTF8 인코딩만 지원하고 있는 데다 장비는 System.Text.Encoding.Default 인코딩으로 전송한 한글을 인식한다는 것입니다.<br /> <br /> 재미있군요. ^^ 한글 윈도우에서 System.Text.Encoding.Default 방식은 곧 ks_c_5601-1987 인코딩을 사용했다는 것입니다. 그렇다면 장비 측에서 ks_c_5601-1987 인코딩 방식의 한글을 지원한다는 것인데, 제가 FA 산업 분야는 잘 몰라서 할 말이 없지만 장비에서 다른 표준 인코딩도 아니고 국내 특화된 ks_c_5601-1987을 지원한다는 것이 의외입니다.<br /> <br /> 암튼, 그렇다고 하니... ^^ ks_c_5601-1987 인코딩을 할 수 있는 메서드를 만들어야 합니다. 일단, C#의 string 타입은 내부적으로 UTF-16 인코딩을 따르기 때문에 해당 string을 char 배열로 바꾼 다음 곧바로 바이트 배열로 뽑아내면 그건 UTF-16 인코딩이 된 결과물이 됩니다. 비교를 위해 다음과 같이 코딩을 할 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > using System; using System.Collections.Generic; namespace encode_test { class Program { static void Main(string[] args) { string text = "한글 테스트"; byte[] contents1 = System.Text.Encoding.Unicode.GetBytes(text); Console.WriteLine(BitConverter.ToString(contents1)); byte[] contents2 = Chars2Bytes(text.ToCharArray()); Console.WriteLine(BitConverter.ToString(contents2)); } public static byte[] Chars2Bytes(char[] charArray) { List<byte> outputs = new List<byte>(); for (int i = 0; i < charArray.Length; i ++) { outputs.Add((byte)(charArray[i] & 0xFF)); outputs.Add((byte)(charArray[i] >> 8)); } return outputs.ToArray(); } } } </pre> <br /> 당연히 실행 결과는 동일하게 나오겠죠? ^^<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 5C-D5-00-AE-20-00-4C-D1-A4-C2-B8-D2 5C-D5-00-AE-20-00-4C-D1-A4-C2-B8-D2 </pre> <br /> 우리가 원하는 것은 ks_c_5601-1987이기 때문에 유니코드를 ks_c_5601-1987로 변환해주는 테이블이 필요합니다. 다행히 이를 찾아보면 다음과 같은 텍스트 파일을 구할 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > ksc5601.txt ; <a target='tab' href='http://opensource.apple.com/source/tcl/tcl-10/tcl/tools/encoding/ksc5601.txt'>http://opensource.apple.com/source/tcl/tcl-10/tcl/tools/encoding/ksc5601.txt</a> </pre> <br /> 대략 다음과 같은 내용을 담고 있는데요.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > # What is enclosed below is the mapping between KS C 5601-1987 # and Unicode 2.0. It's automatically generated from KSC5601.TXT # (at ftp://ftp.unicode.org/Public/MAPPING/EASTASIA/KSC) which is # actually NOT the mapping between KS C 5601-1992 and Unicode 2.0 # BUT the mapping table between UHC(Microsoft Unified Hangul Code) # and Unicode 2.0. Hence, in this pacakge, I renamed it as UHC.TXT # # The Unix command used is # egrep '^0x' < KSC5601.TXT | \ # egrep -v '^0x([8-9]...|A0..|..[4-9].|..A0)' | perl tab.pl # # where tab.pl is as following #----------tab.pl # $n=0; # while (<>) { # local($euck, $ucs4, @rest) = split; # local($u)=hex($ucs4); # local($k)=hex($euck); # printf ("0x%04X 0x%04X %s\n",$k-0x8080, $u,join(' ',@rest)); # } # # <span style='color: blue; font-weight: bold'>Column #1 : KS C 5601-1987</span>(KS C 5601-1992 excluding addtional Hangul # syllables defined for Johab encoding in Annex 3) # in hex as 0xXXXX # <span style='color: blue; font-weight: bold'>Column #2 : the Unicode</span> (in hex as 0xXXXX) # Column #3 : the Unicode name (following a comment sign, '#') # The number of characters enumerated in this table is 8824, the # as listed in KS C 5601-987 # # # The entries are in KS C 5601-1987 order # You can use the following algorithms to convert the hex form # of KS C 5601 to other forms # <span style='color: blue; font-weight: bold'>To get EUCKorea(EUC-KR) code points, add 0x8080.</span> # To get row(Hang) and column(Yol) as used in KS C 5601-1987 manual, # first subtract 0x2020. Then # the high and low bytes correspond to the row(Hang) and the column(Yol), # respectively 0x2121 0x3000 # IDEOGRAPHIC SPACE 0x2122 0x3001 # IDEOGRAPHIC COMMA 0x2123 0x3002 # IDEOGRAPHIC FULL STOP 0x2124 0x00B7 # MIDDLE DOT 0x2125 0x2025 # TWO DOT LEADER 0x2126 0x2026 # HORIZONTAL ELLIPSIS 0x2127 0x00A8 # DIAERESIS ....[이하 생략]... </pre> <br /> 즉 첫 번째 컬럼의 값이 (0x8080을 더하면) "KS C 5601-1987" 값이고, 두 번째 값이 유니코드 대응입니다. 이 텍스트를 동적으로 로드해서 사용하는 것도 좋지만 보통 매핑 테이블을 만들어 두는 것이 더 효율적이기 때문에 미리 C# 코드로 변환해 두는 것이 좋습니다. 하지만, 텍스트 파일 내용이 너무 길기 때문에 일일이 변환하는 것은 불편하므로 다음과 같이 C# 코드로 출력해 주는 메서드를 이용해 파일로 만듭니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > public static void Output() { Console.WriteLine("Dictionary<char, char> unicode2ksc = new Dictionary<char,char>();"); foreach (string line in File.ReadAllLines("ksc5601.txt")) { string[] splits = line.Split('#'); if (splits.Length < 2 || string.IsNullOrEmpty(splits[0]) == true) { continue; } string[] ksc2unicode = splits[0].Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (ksc2unicode.Length < 2) { continue; } int ksc = Convert.ToInt32(ksc2unicode[0], 16) + 0x8080; int unicode = Convert.ToInt32(ksc2unicode[1], 16); Console.WriteLine(string.Format("unicode2ksc.Add((char){0}, (char){1});", unicode, ksc)); } } </pre> <br /> 출력된 내용을 C# 파일에 적절하게 복사하면 다음과 같이 유니코드에서 ks_c_5601-1987로 변환하는 메서드를 만들 수 있습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > using System; using System.Collections.Generic; using System.IO; namespace encode_test { public class ksc5601 { <span style='color: blue; font-weight: bold'>static Dictionary<char, char> unicode2ksc = new Dictionary<char, char>();</span> static ksc5601() { <span style='color: blue; font-weight: bold'> unicode2ksc.Add((char)12288, (char)41377); unicode2ksc.Add((char)12289, (char)41378); // ...[생략]... unicode2ksc.Add((char)32690, (char)65021); unicode2ksc.Add((char)35440, (char)65022);</span> } public static byte[] unicode2ksc5601(string text) { List<byte> contents = new List<byte>(); foreach (char ch in text) { if (unicode2ksc.ContainsKey(ch) == true) { char ksc = (char)(unicode2ksc[ch]); contents.Add((byte)(ksc >> 8)); contents.Add((byte)(ksc & 0xFF)); } else if (ch < byte.MaxValue) { contents.Add((byte)ch); } else { throw new ApplicationException("Not supported character: " + ch); } } return contents.ToArray(); } } } </pre> <br /> 이제 System.Text.Encoding.Default와 출력이 같은지 테스트 해볼까요? ^^<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > string text = "한글 테스트"; { byte[] contents1 = System.Text.Encoding.Default.GetBytes(text); Console.WriteLine(BitConverter.ToString(contents1)); byte[] contents2 = ksc5601.unicode2ksc5601(text); Console.WriteLine(BitConverter.ToString(contents2)); } // 출력결과 C7-D1-B1-DB-20-C5-D7-BD-BA-C6-AE C7-D1-B1-DB-20-C5-D7-BD-BA-C6-AE </pre> <br /> 참고로, ".NET Micro Framework"는 제네릭 구문을 지원하지 않기 때문에 위의 코드를 C# 1.0 문법으로 변환해 주어야 합니다. 그건... 각자의 숙제로!<br /> <br /> (<a target='tab' href='http://www.sysnet.pe.kr/bbs/DownloadAttachment.aspx?fid=839&boardid=331301885'>테스트 코드는 첨부 파일</a>로 넣어두었습니다.)<br /> </p><br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
1719
(왼쪽의 숫자를 입력해야 합니다.)