String to hex을 hex byte array
소켓통신은 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[] 에 담긴 형태와
이러한 작업을 거친 것의 차이가 있는것인지다.
확인해 봐야할 문제다.