안드로이드 개발 질문/답변
(글 수 45,052)
우선...코드를 먼저 보시는 게 설명이 쉬울 듯 하여, 코드를 올립니다.
String fileEncoding=System.getProperty("file.encoding");
System.out.println("file.encoding = "+fileEncoding);
String Encoding = "한글";
try {
String toBinaryRaw = new String(Encoding.getBytes() );
System.out.println("Binary Raw Data:" + toBinaryRaw );
ShowAllByte( toBinaryRaw );
String toISO_8859 = new String(Encoding.getBytes(),"ISO-8859-1");
System.out.println("ISO-8859-1 Encoding : " + toISO_8859 );
ShowAllByte( toISO_8859 );
String toUtf_8 = new String(Encoding.getBytes(),"utf-8");
System.out.println("UTF-8 Encoding : " + toUtf_8);
ShowAllByte( toUtf_8 );
String toEUCKR = new String(Encoding.getBytes(),"euc-kr");
System.out.println("toEUCKR Encoding : " + toEUCKR );
ShowAllByte( toEUCKR );
String toUTF8_EUCKR = new String( Encoding.getBytes("utf-8"),"euc-kr");
System.out.println("toUTF8_EUCKR Encoding : " + toUTF8_EUCKR );
ShowAllByte( toUTF8_EUCKR );
String toksc5601 = new String(Encoding.getBytes(),"KSC5601");
System.out.println("KSC5601 Encoding : " + toksc5601);
ShowAllByte( toksc5601 );
String toms949 = new String(Encoding.getBytes(),"ms949");
System.out.println("MS949 Encoding : " + toms949);
ShowAllByte( toms949 );
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
보시는 바와 같이, 한글 인코딩 / 디코딩 테스트를 위한 코드입니다.
이클립스 환경은 UTF-8로 되어 있습니다. 그래서 실행시키면
file.encoding = utf-8
Binary Raw Data:한글
Size: 6 Byte: [0xed 0x95 0x9c 0xea 0xb8 0x80 )
ISO-8859-1 Encoding : íê¸
Size: 12 Byte: [0xc3 0xad 0xc2 0x95 0xc2 0x9c 0xc3 0xaa 0xc2 0xb8 0xc2 0x80 )
UTF-8 Encoding : 한글
Size: 6 Byte: [0xed 0x95 0x9c 0xea 0xb8 0x80 )
toEUCKR Encoding : ���
Size: 9 Byte: [0xef 0xbf 0xbd 0xef 0xbf 0xbd 0xef 0xbf 0xbd )
toUTF8_EUCKR Encoding : ���
Size: 9 Byte: [0xef 0xbf 0xbd 0xef 0xbf 0xbd 0xef 0xbf 0xbd )
KSC5601 Encoding : ���
Size: 9 Byte: [0xef 0xbf 0xbd 0xef 0xbf 0xbd 0xef 0xbf 0xbd )
MS949 Encoding : �쒓�
Size: 9 Byte: [0xef 0xbf 0xbd 0xec 0x92 0x93 0xef 0xbf 0xbd )
이와 같이 나옵니다.
서버가 EUC-KR이라, Client쪽에서 UTF-8 -> EUC-KR로 바꾸어 주려 합니다.
근데, 처음에 new String( Encoding.getBytes(), "EUC-KR"); 해도 자꾸 한글이 깨지길레, 아무래도 이상해서 Client에서 전송 전에 Binary값을 찍어 보니 위와 같은 결과를 얻었습니다.
저는 String( Encoding.getBytes(), "EUC-KR" ) 하면 6Byte의 UTF-8 "한글" 이 4Byte의 EUC-KR "한글" 로 바뀔 거라고 생각했는데, 실제로 찍어보니 6바이트가 아니라 9바이트가 됐네요?
저걸 new String( Encoding.getBytes("UTF-8"), "EUC-KR"); 로도 해 봤습니다만...마찬가지구요.
인터넷 뒤져보면 다른 분들은 단순히 String( text.getBytes( FromEncode ), ToEncode ) 만으로도 문제없이 사용하시는 듯 한데,
저는 뭐가 문제인지 모르겠습니다.
혹시 제가 이해 자체가 잘못되었다면 잘못된 부분을 언급해 주시면 감사하겠구요.
만일 비슷한 경우를 겪으셨거나, 혹은 조언이 있으시다면, 주저없이 알려 주시면 대단히 감사하겠습니다.
이상입니다. 좋은 저녁 되시기 바랍니다.
여름철 메뚜기가 마냥 부러운 1人
2010.07.16 21:31:43
안드로이드 프로그래밍 경험은 없지만. 기본 Java 지식으로 답을 드리겠습니다.
1. 일단 new String(text.getBytes(fromEncode), ToEncode) 구문은 잊어주세요. 이 방식은 Java 초창기 시절 tomcat 같은데서 HTTP로 받은 파라메터의 인코딩이 무조건 ISO_8859로 강제 인코딩 되서 들어오는 문제가 있었는데, 그걸 잡으려고 다시 강제로 깨진 문자열을 한글로 바꾸는거였습니다만. 일단 제대로 Java 상에서 인코딩 된 경우. (위 예제에서는 text = "한글"이라고 제대로 들어가 있음) 전혀 사용해서는 안되는 구문입니다.
2. Java에서 사용하는 것은 "유니코드" 이거 하나 밖에 없습니다. String은 까서 보면 char[]이고, char하나 하나는 결국 유니코드 문자입니다. 즉 Java에서 쓰는 모든 캐릭터는 "유니코드"라는 점을 기억해 두셔야 합니다. 그러면 "UTF-8"은 "Unicode Transform Format" 즉 유니코드를 다른 곳으로 전송하기 위한 포맷입니다 (즉 "UTF-8"은 유니코드가 아닙니다. 혼돈하시면 안됩니다. 자바에서 쓰는 char는 "USC-2" 포맷을 약간 변경한 것으로 유니코드를 16-bit로 표현한 것입니다.)
3. 그럼 "UTF-8", "EUC-KR" 등은 어디서 쓰는 것이냐 하면, 자바의 char(USC-2)를 네트워크로 전송하거나 파일로 기록할 때 사용하는 일종의 변환 포맷이라고 보시면 됩니다. 즉 이런 File I/O나 Network I/O를 하기 전에는 구지 제대로 되어 있는 String을 String.getBytes() 등으로 byte로 변환하실 필요 없습니다. 질문하신 분의 경우에는 서버쪽에서 "EUC-KR"으로 송수신하기를 원하기 때문에 서버로 줄 때
byte[] eucBytes = text.getBytes("EUC-KR");
이렇게 해서 euc_kr로 생성된 바이트들을 네트워크로 전송하고, 반대로 받을 때는
String text = new String(eucBytes, "EUC-KR");
이렇게 네트워크를 통해서 euc_kr로 받은 바이트들을 Java의 String으로 만들면 됩니다.
4. 이론은 이렇습니다만. 실제로 이렇게 하면 생기는 문제가 전송할 때는 그냥 보내면 되는데, 받을 때는 EUC-KR의 문자열 끝이 어딘지 확인해서 적당히 끊어줘야 제가 위에 적은 방식으로 String으로 변환할 수 있는데 여간 귀찮은 일이 아닙니다. 그래서 java.io에 보시면 Reader와 Writer라는게 있습니다. 네트워크로 이 작업을 한다고 생각해보시면 네트워크 소켓을 통해서 바이트로 데이타를 주고 받는 InputStream과 OutputStream을 얻을 수 있을껍니다. 그러면
OutputStreamWriter writer = new OutputStreamWriter(socket.getOutputStream(), "EUC-KR"));
writer.write(text);
이렇게 하면 text를 네트워크를 통해서 쓸 때 EUC-KR로 변환해서 쏘아주고,
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), "EUC-KR")));
String text = reader.readLine();
이렇게 하면 네트워크를 통해서 받은 EUC-KR을 Java의 String으로 변환해줍니다.