자바 기본 유형의 바이트 순서 변환

author : Yoon Kyung Koo(yoonforh@yahoo.com)
Copyright (c) 1999-2002 Yoon Kyung Koo, All rights reserved.
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를 다른 엔디안 값으로 바꾸는 원리입니다.


// Htonl.java
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를 변경할 때에는 다음과 같이 간편하게 할 수 있습니다.
// Htonl2.java

class Htonl2 {
	public static void main(String args[]) {
		if (args.length<1) {
			System.out.println("Usage : java Htonl2 ");
			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)));
    }

}

이 페이지는 1999년 9월 10일에 처음 만들어졌습니다.
튜토리얼 페이지로 돌아가기
Last modified: Fri Jul 05 13:18:31 +0900 2002