본문 바로가기
IT/JAVA

Java 엔디안 변경

by 최고영회 2014. 5. 20.
728x90
반응형
SMALL
LITTLE ENDIAN은 LSB가 처음에 나오고
BIG ENDIAN은 MSB가 처음에 나옵니다.
그리고 네트웍 바이트 순서는 BIG ENDIAN 이다.
만약 4바이트 (즉, 자바의 int, 32비트 기계에서 C의 int나 long)라면
자바나 Big Endian에서 1-2-3-4 순서로 바이트가 배치되면
Little Endian은 4-3-2-1 순서로 바이트를 해석해야 한다.
즉, int type인 숫자 1은 little endian에서는 (1, 0, 0, 0)로 표시되며
big endian에서는 (0, 0, 0, 1)로 표시된다.

float나 double의 경우는 시스템에 따라 좀더 복잡합니다.
하지만 IEEE 754를 따르는 경우에는 단순히 바이트 순서만 바꾸면 해석 가능하다.

C에서
float은 보통 32비트(4바이트)이고 double은 보통 64비트(8바이트)입니다.
자바도 이에 준할 것.
따라서 빅 엔디안에서 더블을 표현할 때 1-2-3-4-5-6-7-8 바이트 순서라면
리틀 엔디안에서는 8-7-6-5-4-3-2-1 바이트 순서로 해석하면 됨

즉, long type인 숫자 1, 
즉 1L은 little endian에서는 (1, 0, 0, 0, 0, 0, 0, 0)로 표시되며 big endian에서는 (0, 0, 0, 0, 0, 0, 0, 1)로 표시
실제 바이트 배열로 넘어온 값을 double이나 float로 변환하는 데에는 (혹은 그 반대의 경우에는)

다음 메소드들을 사용 static int Float.floatToIntBits(float); static int Float.floatToRawIntBits(float); static float Float.intBitsToFloat(int); static long Double.doubleToLongBits(double); static long Double.doubleToRawLongBits(double); static double Double.longBitsToDouble(long); 자바 int를 다른 엔디안 값으로 바꾸는 원리 class Htonl { public static void main(String args[]) { if (args.length<1) { System.out.println("Usage : java Htonl "); System.exit(0); } int value=Integer.parseInt(args[0]);

// all java integer is BIG-ENDIAN(network byte-order) byte[] bytes=new byte[4]; bytes[0]=(byte)((value&0xFF000000)>>24); bytes[1]=(byte)((value&0x00FF0000)>>16); bytes[2]=(byte)((value&0x0000FF00)>>8); bytes[3]=(byte) (value&0x000000FF); int newValue = 0; newValue |= (((int)bytes[3])<<24)&0xFF000000; newValue |= (((int)bytes[2])<<16)&0xFF0000; newValue |= (((int)bytes[1])<<8)&0xFF00; newValue |= (((int)bytes[0]))&0xFF; System.out.println("big endian value = 0x" + Integer.toHexString(value) + " ("+bytes[0]+","+bytes[1]+","+bytes[2]+","+bytes[3]+")"); System.out.println("little endian value = 0x" + Integer.toHexString(newValue) + " ("+bytes[3]+","+bytes[2]+","+bytes[1]+","+bytes[0]+")"); } }


원리적으로는 위와 같지만 실제 byte order를 변경할 때에는 다음과 같이 간편하게 할 수 있다 class Htonl { public static void main(String args[]) { if (args.length<1) { System.out.println("Usage : java Htonl"); System.exit(0); } int value=Integer.parseInt(args[0]); int newValue = swap(value); System.out.println("big endian value = 0x" + Integer.toHexString(value) + ", little endian value = 0x" + Integer.toHexString(newValue)); } /* * Swapping byte orders of given numeric types */ static short swap(short x) { return (short)((x << 8) | ((x >> 8) & 0xff)); } static char swap(char x) { return (char)((x << 8) | ((x >> 8) & 0xff)); } static int swap(int x) { return (int)((swap((short)x) << 16) | swap((short)(x >> 16)) & 0xffff)); } static long swap(long x) { return (long)(((long)swap((int)(x)) << 32) | ((long)swap((int)(x >> 32)) & 0xffffffffL)); } static float swap(float x) { return Float.intBitsToFloat(swap(Float.floatToRawIntBits(x))); } static double swap(double x) { return Double.longBitsToDouble(swap(Double.doubleToRawLongBits(x))); } }


----------------------------------------------------------------------------------------------------------------------------------

ByteBuffer 를 사용하여 아래와 같이 편하게 쓸수도 있음

byte[] x=new byte[100]; ByteBuffer buf=ByteBuffer.allocate(100); buf.putInt(0x01020304); buf.putChar((char)0x0506); buf.putLong(0x0102030405060708L); buf.putDouble(3.3e15); buf.position(0); buf.get(x); System.out.println(x[0]+","+x[1]+","+x[2]+","+x[3]); buf.position(0); System.out.println(Integer.toHexString(buf.getInt())); System.out.println(Integer.toHexString(buf.getChar())); System.out.println(Long.toHexString(buf.getLong())); System.out.println(buf.getDouble());  

 

System.out.println("=============================");

 

buf.order(ByteOrder.LITTLE_ENDIAN); buf.position(0); buf.get(x); System.out.println(x[0]+","+x[1]+","+x[2]+","+x[3]); buf.position(0); System.out.println(Integer.toHexString(buf.getInt())); System.out.println(Integer.toHexString(buf.getChar())); System.out.println(Long.toHexString(buf.getLong())); System.out.println(buf.getDouble());


728x90
반응형
LIST