Java에서 바이트 배열을 정수로 변환하거나 그 반대로 변환


139

Java에서 바이트 배열에 일부 데이터를 저장하고 싶습니다. 기본적으로 숫자 당 최대 2 바이트를 사용할 수있는 숫자입니다.

정수를 2 바이트 길이의 바이트 배열로 변환하거나 그 반대로 변환하는 방법을 알고 싶습니다. 인터넷에서 많은 솔루션을 찾았지만 대부분 코드에서 일어나는 일을 설명하지 않습니다. 실제로 이해하지 못하는 많은 변화가 있기 때문에 기본 설명에 감사드립니다.


4
얼마나 않는 당신은 비트 이동에 대한 이해? 문제는 실제로 바이트 배열로의 변환에 대한 것보다 "비트 이동이 무엇을 하는가"인 것처럼 들립니다. 실제로 변환이 어떻게 작동하는지 이해하고 싶다면.
Jon Skeet

1
(확실히 말하면, 나는 어느 질문에 대해서는 괜찮지 만, 실제로 어떤 질문에 대답하고 싶은지 분명히 밝힐 가치 가 있습니다. 그 방법이 당신에게 더 유용한 답변을 얻을 가능성이 높습니다.)
Jon Skeet

좋아, 요점을 알았다! 발언 감사합니다. 나는 비트 시프트가 무엇인지 알고 있지만 바이트 배열을 변환하는 데 사용 된 것을 아직 이해하지 못했습니다.
Chris

3
@prekageo와 Jeff Mercado 두 가지 답변에 감사드립니다. prekageo는이 작업을 수행하는 방법에 대한 좋은 설명을 제공했습니다. 그것은 나에게 훨씬 더 명확해진다. 그리고 Jeff Mercados 솔루션은 내가 가진 문제를 해결했습니다.
Chris

답변:


230

java.nio네임 스페이스 에있는 클래스, 특히을 사용하십시오 ByteBuffer. 그것은 당신을 위해 모든 일을 할 수 있습니다.

byte[] arr = { 0x00, 0x01 };
ByteBuffer wrapped = ByteBuffer.wrap(arr); // big-endian by default
short num = wrapped.getShort(); // 1

ByteBuffer dbuf = ByteBuffer.allocate(2);
dbuf.putShort(num);
byte[] bytes = dbuf.array(); // { 0, 1 }

2
바이트 배열에 1 또는 2 개의 정수만 포함되어 있으면 너무 비쌉니까? 를 생성하는 비용에 대해 잘 모르겠습니다 ByteBuffer.
Meow Cat 2012 년

2-4 바이트 단위로 이진 데이터를 얼마나 자주 작업하고 있습니까? 정말? 정상적인 구현은 BUFSIZ 청크 (일반적으로 4kb)에서 작동하거나이 세부 사항을 숨기는 다른 IO 라이브러리를 사용합니다. 프레임 워크 내에는 데이터 버퍼 작업에 도움이되는 전체 라이브러리가 있습니다. 정당한 이유없이 일반적인 작업을 수행 할 때 (퍼포먼스 또는 기타 중요한 작업) 자신과 다른 코드 관리자에게 장애를 일으 킵니다. 이 버퍼는 단지 배열에서 작동하는 래퍼 일뿐입니다.
Jeff Mercado

어떻게 추상 클래스를 인스턴스화 할 수 있습니까?

1
@JaveneCPPMcGowan이 답변에는 직접적인 인스턴스화가 없습니다. 팩토리 메소드 wrap와 를 의미하는 경우 allocate추상 클래스의 인스턴스를 반환하지 않습니다 ByteBuffer.
Marko Topolnik

3 바이트 보폭 솔루션이 아닙니다. 우리는 얻을 수 있습니다 Char, Short, Int. 나는 매 4 바이트로 채울 수 있고 매번 네 번째를 버릴 수 있다고 가정하지만 오히려 그렇지 않습니다.
John

128
byte[] toByteArray(int value) {
     return  ByteBuffer.allocate(4).putInt(value).array();
}

byte[] toByteArray(int value) {
    return new byte[] { 
        (byte)(value >> 24),
        (byte)(value >> 16),
        (byte)(value >> 8),
        (byte)value };
}

int fromByteArray(byte[] bytes) {
     return ByteBuffer.wrap(bytes).getInt();
}
// packing an array of 4 bytes to an int, big endian, minimal parentheses
// operator precedence: <<, &, | 
// when operators of equal precedence (here bitwise OR) appear in the same expression, they are evaluated from left to right
int fromByteArray(byte[] bytes) {
     return bytes[0] << 24 | (bytes[1] & 0xFF) << 16 | (bytes[2] & 0xFF) << 8 | (bytes[3] & 0xFF);
}

// packing an array of 4 bytes to an int, big endian, clean code
int fromByteArray(byte[] bytes) {
     return ((bytes[0] & 0xFF) << 24) | 
            ((bytes[1] & 0xFF) << 16) | 
            ((bytes[2] & 0xFF) << 8 ) | 
            ((bytes[3] & 0xFF) << 0 );
}

부호있는 바이트를 int로 패킹 할 때 각 바이트는 산술 승격 규칙 (JLS, 변환 및 승격에 설명 됨)으로 인해 32 비트 (0 확장이 아닌)로 확장되므로 마스크 해제해야합니다.

Joshua Bloch와 Neal Gafter의 Java Puzzlers ( "모든 바이트에서 큰 기쁨")에 설명 된 흥미로운 퍼즐이 있습니다. 바이트 값을 int 값과 비교할 때 바이트는 int로 부호 확장되고이 값은 다른 int와 비교됩니다.

byte[] bytes = (…)
if (bytes[0] == 0xFF) {
   // dead code, bytes[0] is in the range [-128,127] and thus never equal to 255
}

16 비트 부호없는 정수 유형 인 char을 제외하고 모든 숫자 유형은 Java로 서명됩니다.


나는 & 0xFF불필요 하다고 생각합니다 .
Ori Popowski

11
@LeifEricson 나는 & 0xFFJVM이 부호있는 바이트를 비트 세트로 정수로 변환하도록 지시하기 때문에 s가 필요 하다고 생각합니다 . 그렇지 않으면 바이트 -1 (0xFF)이 int -1 (0xFFFFFFFF)로 바뀝니다. 나는 틀릴 수 있고, 그것이 아프더라도 일을 더 명확하게 만듭니다.
coderforlife

4
& 0xFF는 실제로 필수입니다. byte b = 0; b |= 0x88; System.out.println(Integer.toString(b, 16)); //Output: -78 System.out.println(Integer.toString(b & 0xFF, 16)); //Output: 88
HBN

1
@ptntialunrlsd 실제로는 아닙니다. 당신이 수행하기 전에 & 에 작업을 byte0xFF로 (으로 int), JVM은 캐스팅됩니다 byteint확장 1 또는 0 확장 된 하여 첫 번째 비트 선도에 따라. Java 에는 부호없는 바이트 가 없으며 byte항상 부호가 있습니다.
Nier

2
그것의 문서에 따르면, 4 바이트 이상이라면 바이트 배열의 크기에 바이트 배열, 임금의 관심에서 구문 분석 INT는 때 ByteBuffer.getInt(): Reads the next four bytes at this buffer's current position, 첫 번째 4 바이트 구문 분석됩니다, 당신이 원하는 무엇을하지 않아야한다.
Bin

57

가변 길이 바이트에 BigInteger를 사용할 수도 있습니다. 필요에 따라 long, int 또는 short로 변환 할 수 있습니다.

new BigInteger(bytes).intValue();

또는 극성을 나타 내기 위해 :

new BigInteger(1, bytes).intValue();

바이트를 다시 얻으려면 :

new BigInteger(bytes).toByteArray()

1
1.8 이후, 그것의 참고 intValueExact하지intValue
Abhijit 사카

5

기본 구현은 다음과 같습니다.

public class Test {
    public static void main(String[] args) {
        int[] input = new int[] { 0x1234, 0x5678, 0x9abc };
        byte[] output = new byte[input.length * 2];

        for (int i = 0, j = 0; i < input.length; i++, j+=2) {
            output[j] = (byte)(input[i] & 0xff);
            output[j+1] = (byte)((input[i] >> 8) & 0xff);
        }

        for (int i = 0; i < output.length; i++)
            System.out.format("%02x\n",output[i]);
    }
}

내용을 이해하기 위해이 WP 기사를 읽을 수 있습니다 : http://en.wikipedia.org/wiki/Endianness

위의 소스 코드가 출력 34 12 78 56 bc 9a됩니다. 처음 2 바이트 ( 34 12)는 첫 번째 정수 등을 나타냅니다. 위의 소스 코드는 작은 엔디안 형식의 정수를 인코딩합니다.


2
/** length should be less than 4 (for int) **/
public long byteToInt(byte[] bytes, int length) {
        int val = 0;
        if(length>4) throw new RuntimeException("Too big to fit in int");
        for (int i = 0; i < length; i++) {
            val=val<<8;
            val=val|(bytes[i] & 0xFF);
        }
        return val;
    }

0

비트에서 읽어야하는 요구 사항이있는 사람은 3 비트 만 읽어야하지만 부호있는 정수가 필요하다고 말하면 다음을 사용하십시오.

data is of type: java.util.BitSet

new BigInteger(data.toByteArray).intValue() << 32 - 3 >> 32 - 3

매직 번호 는 사용중인 비트3 수가 아닌 바이트 수로 대체 될 수 있습니다 .


0

구아바 에는 종종 필요한 것이 있습니다.

바이트 배열에서 int로 이동하려면 Ints.fromBytesArraydoc here

int에서 바이트 배열로 이동하려면 : Ints.toByteArraydoc here


-7

이것이 int로 캐스팅하는 가장 좋은 모드라고 생각합니다.

   public int ByteToint(Byte B){
        String comb;
        int out=0;
        comb=B+"";
        salida= Integer.parseInt(comb);
        out=out+128;
        return out;
    }

첫 번째 바이트를 문자열로 변환

comb=B+"";

다음 단계는 int로 변환됩니다.

out= Integer.parseInt(comb);

그러나 바이트는이 이유로 인해 -128에서 127까지의 분노에 해당합니다. 범위 0에서 255까지 사용하는 것이 더 좋다고 생각하면됩니다.

out=out+256;

이것은 잘못이다. 바이트 0x01을 고려하십시오. 귀하의 방법은 잘못된 129를 출력합니다. 0x01은 정수 1을 출력해야합니다. parseInt에서 얻은 정수가 음수 인 경우에만 128을 추가해야합니다.
disklosr

256이 아닌 256을 추가해야한다는 의미입니다. 나중에 편집 할 수 없습니다.
disklosr

다른 사용자에게 유용 할 수 있으므로 256을 추가하도록 게시물을 변경했습니다!
apmartin1991

이것은 많은 캐스팅을 수행하고 성능을 저하시킬 수있는 새로운 객체를 생성합니다 (루프에서 이것을 생각하십시오). 수를 구문 분석하는 방법에 대한 힌트는 Integer.toString () 메소드를 확인하십시오.
Marcos Vasconcelos

또한 스택 오버플로에 코드를 게시 할 때 요점은 쉽게 이해되는 코드를 게시하는 것입니다. 이해하기 쉬운 코드에는 이해할 수있는 식별자 가 있어야합니다 . 그리고 스택 오버 플로우에서 이해할 수있는 것은 반드시 영어로 의미 합니다.
Mike Nakis
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.