티스토리 뷰

세 줄 요약.


1. JAVA 의 String 클래스는 유니코드로 처리되는 char 의 배열 이외에 어떠한 인코딩 정보를 갖고 있지 않는다. 

2. String.getByte('인코딩명') 을 사용하여 인코딩 할 수 있으며, new String(byte[], "인코딩명") 을 사용하여  디코딩 할 수 있다/.

3. EUC-KR 에서 UTF-8 으로 바꾸기 위해서는 EUC-KR ---> java.lang.String ----> UTF-8 과 같은 방식으로 변환 할 수 있다.



 기본적으로 자바의 String 클래스는 2 byte 크기의 유니코드를 사용하여 문자열을 처리하는 Character 배열을 감싸고 있는 형태이다.

 https://docs.oracle.com/javase/8/docs/api/java/lang/Character.html 참고. 


 JDK 1.8 의 String 클래스의 코드를 보면 아래와 같이...


public final class String implements java.io.Serializable, Comparable<String>, CharSequence { /** The value is used for character storage. */ private final char value[]; /** Cache the hash code for the string */ private int hash; // Default to 0 /** use serialVersionUID from JDK 1.0.2 for interoperability */ private static final long serialVersionUID = -6849794470754667710L; /** * Class String is special cased within the Serialization Stream Protocol. * * A String instance is written into an ObjectOutputStream according to * <a href="{@docRoot}/../platform/serialization/spec/output.html"> * Object Serialization Specification, Section 6.2, "Stream Elements"</a> */ private static final ObjectStreamField[] serialPersistentFields = new ObjectStreamField[0];



달랑 네 개의 필드를 확인할 수 있는데, 여기에 문자열 관련된 값이 저장되는 것은 value[] 가 유일하다.



String 클래스의  getBytes()  메소드를 사용하여 String 을 다른 인코딩으로 변환할 수 있으며, 이 것은 즉 2byte 의 유니코드가 다른 인코딩으로 변환되어 반환되는 것이다.


  getBytes() 사용시 아무런 인자값을 넣지 않고 호출한다면, 그리고 JVM 실행 옵션으로 인코딩을 정의하지 않았다면 ( 예 : -Dsun.jnu.encoding=UTF-8 -Dfile.encoding=UTF-8) 시스템 기본 인코딩으로 변환되어 나올 것이다. 만약 윈도우에서 아무런 옵션 없이 JVM 을 실행하여 String 에 대하여 getBytes() 를 호출한다면 MS949 로 인코딩된 byte 배열이 튀어나올 것이다. (윈도우에서 돌아가는 JVM은 기본적으로 MS949 를 사용하기 때문이다.) 이렇게 아무런 인자값 없이 getBytes() 를 호출한다면 내부적으로 JVM 기본 인코딩을 정보를 가져오는 getProperty("file.encoding") 을 호출하여 얻은 결과 값으로 시스템 인코딩 값으로 인코딩 한다.  그렇기 때문에 String 으로부터 자신이 원하는 인코딩 바이트 배열을 얻기 위해서는 아래 예제처럼 인자값으로 인코딩명을 넣어줘야 한다.


Unicode String --> euc-kr :

// String 을 euc-kr 인코딩으로 변환하여 반환. String helloString = "안녕하세요?"; byte[] euckrStrBuffer = helloString.getBytes("euc-kr");




위 구현은 내부적으로 String 을 인코드 혹은 디코드 해주는 StringCoding 클래스의 encode 라는 이름의 static 메소드를 이용한다. 

하지만, StringCoding 클래스는 protected 클래스기 때문에 직접적으로 사용할 수 없다.

하지만 String.getBytes("euc-kr")  메소드를 쓰는 방법 이외에도 같이  nio 의 Charset 을 이용하여 String 을 euc-kr 로 변환할 수 있다.



Unicode String --> euc-kr (nio.charset 사용) :

Charset euckrCharset = Charset.forName("euc-kr");
ByteBuffer byteBuffer = euckrCharset.encode(helloString);
byte[] euckrStringBuffer = new byte[byteBuffer.remaining()];
byteBuffer.get(euckrStringBuffer);




 다음으로 인코딩된 문자열의 바이트 배열을 다시 String 으로 만드는 방법이다. 


euc-kr --> Unicode String :

String helloString = "안녕하세요"; 
byte[] euckrStringBuffer  = helloString.getBytes(Charset.forName("euc-kr"));
// euc-kr 로 변환된 byte 문자열을 다시 유니코드 String 으로 변환.
// String 생성자의 
// 첫 번째 인자로 문자열 byte 배열을  넣어주고, 
// 두 번째 인자로 byte 배열의 인코딩 값을 넣어준다.
String decodedHelloString = new String(euckrStringBuffer, "euc-kr");



이 것 또한 마찬가지로 nio 의 Charset 를 이용하여 디코드 할 수 있다.


euc-kr --> Unicode String (nio.charset 사용) :

Charset euckrCharset = Charset.forName("euc-kr");
CharBuffer charBuffer = euckrCharset.decode(ByteBuffer.wrap(euckrStringBuffer));
String decodedHelloString = charBuffer.toString();



System.out.Println 를 찍어보면 값이 정상적으로 변환된 것을 확인할 수 있다.




그렇다면, euc-kr 을 utf-8 로 변환시키거나 또는 반대로 변환시키고 싶을 때는 어떻게 해야 하는가?

답은 도중에 String 으로 변환하는 과정을 한 번 거치면 된다.



EUC-KR ---> UTF-8 :

String helloString = "안녕하세요. ㄱㄴㄷㄹㅁㅂㅆㅢ 놟쐛씗쀍";
System.out.println("Source : " + helloString);

// String 을 euc-kr 로 인코딩.
byte[] euckrStringBuffer = helloString.getBytes(Charset.forName("euc-kr"));
System.out.println();

System.out.println("euc-kr - length : " + euckrStringBuffer.length);
String decodedFromEucKr = new String(euckrStringBuffer, "euc-kr");
System.out.println("String from euc-kr : " + decodedFromEucKr);

// String 을 utf-8 로 인코딩.

byte[] utf8StringBuffer = decodedFromEucKr.getBytes("utf-8"); System.out.println(); System.out.println("utf-8 - length : " + utf8StringBuffer.length); String decodedFromUtf8 = new String(utf8StringBuffer, "utf-8"); System.out.println("String from utf-8 : " + decodedFromUtf8);



즉 위 코드는 


  euc-kr ---> JAVA String 객체(유니코드)  ---> utf-8


과 같은 과정으로 인코딩 변환이 되는 것이다.


하지만, 아래 결과를 살펴보면...


결과:

Source : 안녕하세요. ㄱㄴㄷㄹㅁㅂㅆㅢ 놟쐛씗쀍

euc-kr - length : 33
String from euc-kr : 안녕하세요. ㄱㄴㄷㄹㅁㅂㅆㅢ ????

utf-8 - length : 46
String from utf-8 : 안녕하세요. ㄱㄴㄷㄹㅁㅂㅆㅢ ????



 깨지는 글자가 발생하게 된다.

 이유는 완성형인 euc-kr 이 '놟쐛씗쀍' 과 같은 문자를 지원하지 못하기 때문에 문자열 '안녕하세요. ㄱㄴㄷㄹㅁㅂㅆㅢ 놟쐛씗쀍' 를 인코딩 할 경우 지원하지 못 하는 문자에 대한 손실이 일어나게 되는 것이다. 




댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함