2009년 4월 30일 목요일

네트웍에서 2바이트로 들어오는 unicode를 자바에서 처리하기

개발환경은 JEE 이지만 실제코드와 업무영역은 JSE에 가까워서 JavaSE 카테고리에 넣어둡니다. 이전 자료입니다^^;;


프로젝트 진행중에 클라이언트는 C++로 작성되어져 있고,

서버는 J2EE A/S를 기반으로 작성되어져 있습니다.

여러가지 연동 중에 소켓을 통해서 데이터를 주고 받는 게 있는데, 그 중에 2바이트 유니코드를 받아서 처리해야 하는 부분이 있었습니다.

많은 곳에 찾아봐도 해답을 얻지 못했는데, 하루 밤을 새워 알게 되었습니다.

도움이 되었으면 좋겠군요^^


먼저 네트워크에서는 big-endian byte order를 지켜야 함을 명시합니다.

만약 '홍길동'이란 단어를 실제 유니코드를 표현하면 다음과 같습니다.


\ud64d\uae38\ub3d9


그러나, 네트웍에서는 2바이트로 어떻게 들어올까요?

16진수로 표현하면 다음과 같이 들어오게 됩니다.


0x4d 0x64 0x38 0xua 0xd9 0xb3

쉽게표현하면 위와 같이 들어오는 것이고 이를 그냥 stream으로 네트워크에서는 들어오기 때문에 DataInputStream으로 표현하여 StringBuffer에 넣으면 다음과 같이 나오게 됩니다.


4d6438uad9b3


때문에 이를 다음과 같이 변환해 주어야 합니다. 왜냐하면 네크워크에서는 big-endian으로 들어오기 때문이죠...

그리고, 위의 '홍길동'에서는 0x01과 같이 앞 바이트가 '0'이 들어가는 게 없어서 괜찮은데, 만약 '0'이 들어오면 임의로 '0'을 추가해 주어야 합니다.


예제 소스를 첨부합니다


StringBuffer sb = new StringBuffer();

byte[] buf = new byte[4096];
int pos = dataInputStream.read(buf, 0, 4096);

byte[] stringName = new byte[80];

for ( int i=0; i < pos; i+=2 ) {
    String uniString = "\\u";
    
    i += 1;
    try {
       stringName [i] = buf.getByte();
    } catch (Exception e) {
       // TODO Auto-generated catch block
       e.printStackTrace();
    }


    String tempString1 = Integer.toHexString(stringName [i] & 0x000000FF);
    if ( tempString1.length() == 1 )
      tempString1 = "0" + tempString1;
    uniString += tempString1;

    i -= 1;
    try {
      stringName [i] = buf.getByte();
    } catch (Exception e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }


    String tempString2 = Integer.toHexString(stringName [i] & 0x000000FF);
    if ( tempString2.length() == 1 )
       tempString2 = "0" + tempString2;
    uniString += tempString2;
    
    sb.append(ByteUtil.UnitoStr(uniString));
}


소스를 가능하면 명확하게 하기 위해 노력했습니다^^

모두 행복하게 살았으면 좋겠네요ㅎㅎ

댓글 2개:

badnom :

안녕하세요. 좋은글 감사합니다. ^^ 한가지 궁금한점이 있어서요. 자바 같은 경우 big-endian 으로 알고 있는데, 네트워크도 보통 big-endian을 지키기(?) 때문에 그냥 사용하면 되는게 아닌가 싶네요. C에서 보낼때 endian 변환을 안해준게 아닌지... ^^; 아 그리고 가운데 오타가 있는거 같네요 ^^; 0xd6 0x4d 0xae 0x38 0xb3 0xd9 가 아닐런지......

와이즈앤트 :

@badnom - 2009/05/11 11:01
네트워크에서는 big-endian으로 처리되기 때문에 자바 애플리케이션끼리의 통신은 별다른 문제가 없습니다. 블로그의 글대로 C/C++ 시스템이 Standalone application 이어서 별도의 변환을 처리하지 않아서 서버 측에서 처리해 둔 것을 정리한 내용이었습니다.

벌써 4~5년 전의 일이여서 정확한 스토리는 기억나지 않네요... 오타 지적 감사합니다^^ 다음에 한 번더 코드를 정리해 봐야겠네요^^;; 당시엔 검증을 하고 올렸던 걸로 기억이 나는데...ㅎㅎ