개발/JAVA

String to hex을 hex byte array

보리ing 2019. 3. 22. 11:12

 소켓통신은 byte형태로 송신하고 수신한다. 따라서 보낼 데이터는 바이트 형태로 인코딩을 하게된다.

 1 byte = 8 bit,

 1 bit 는 0,1 2진수 인 것을 모두 잘 알 것이다.

 따라서 1 byte는 8bit 이므로 2^8으로 이루어져 있고 10진수로는 0~255, 

 16진수로는 0~ff까지의 값을 가진다.

 흔히 문자를 바이트로 16진수의 2자리 값으로 나타내며 Apple을 예를들면


   String str = "Apple";


    // 한 글자씩 헥사(Hex)로 출력

    System.out.println(stringToHex(str));

    // 출력 결과: 41 70 70 6C 65


    // 접두사 붙여서 출력

    System.out.println(stringToHex0x(str));

    // 출력 결과: 0x41 0x70 0x70 0x6C 0x65


이러한 형태가 된다. 


 아무튼 이러한 형태로 데이터를 전송하고 받는 간단한 서버를 구축하는 작업을 하고 있는 중 문자를 unicode 형태의 byte 배열로 바꾸라는 얘기를 들었다. 

갑자기 유니코드라니? 문자를 유니코드로 변환하는 것은 알고 있었지만 여기서 또 바이트라니? 여기서 멘붕으로 인한 삽질이 시작되었다.

 String -> unicode 

 unicode -> byte[] 는 

1문자 -> 4자리의 유니코드 -> 4자리의 유니코드 -> 유니코드를 스트링으로 인식 -> 바이트


문자를 바이트로 변환하는 것은 


byte[] bytes = str.getBytes();


문자를 헥사값으로 바꾸는 것은



 public static String escape(String src) {   

  

        int i;   

        char j;   

        

        char[] CharSrc=src.toCharArray();

        

        StringBuffer tmp = new StringBuffer();   

        tmp.ensureCapacity(src.length() * 6);  

        ByteBuffer buffer =  ByteBuffer.allocate(1024);  

        byte[] body = new byte[CharSrc.length*2];       

        for (i = 0; i < CharSrc.length; i++) {   

       

        tmp.append(String.format("\\u%04x ", (int) CharSrc[i]));

       

        }   

        return tmp.toString();   

}   


메소드를 통해 작업하면 된다.



이게 과연 필요한가 의문이 들었고 몇번의 확인 끝에

1문자->1글자의 hex byte가 아닌 1문자 -> 뒤에 00을 가진 2byte 로 표현해달라는 얘기였다.(이것 또한 무슨소리인가 이해가 안 갈 수도 있다)



다시 문자를 헥사 바이트로 변환하는 작업은


문자를 헥사형태의 스트링으로변환 후 바이트에

담는 방법을 사용했다.


  public static String stringToHex(String s) {

    String result = "";


    for (int i = 0; i < s.length(); i++) {

      result += String.format("%02x ", (int) s.charAt(i));

    }


    return result;

  }




public static byte[] hexStringToByteArray(String hexString) {

   

String[] hexString_split = hexString.split(" ");

byte[] hexBytes= new byte[hexString_split.length];

for (int i = 0; i < hexBytes.length; i++) {

hexBytes[i]= (byte)Integer.parseInt(hexString_split[i], 16);

}


    return hexBytes;

}



그리고



    for (int i = 0; i < bytes.length; i++) {

System.out.print(bytes[i]);

}


와 같이 확인을 하면서 삽질이 또 시작되었다.

16진수로 분명 담았는데 출력은 10진수의 값으로 반복해서 나오는 것이었다.

헥사저장이 잘못된 줄 알고 변환하는 여러방법을 써 봤지만 마찬가지였다.

그리고 byte에 저장된 값을 출력할때 포맷을 설정하지 않아

동일한 값이 print()의 기본설정값인(추측이지만) 10진수로 출력 된 것이다.

따라서 

    for (int i = 0; i < hexBytes.length; i++) {

System.out.printf("%02x ", hexBytes[i]);

}


로 하면 기존의 헥사형태로 출력되고,

데이터 역시 정상적으로 문자 -> byte형태가 된 걸로 파악할 수 있다.

여기서 생기는 의문은 string -> getbyte를 통해 byte[] 에 담긴 형태와

이러한 작업을 거친 것의 차이가 있는것인지다.


확인해 봐야할 문제다.