Java에서 바이트 배열을 어떻게 초기화합니까?


138

자바에서 바이트 배열 형태로 일부 상수 값 (UUID)을 저장해야하며 정적 배열을 초기화하는 가장 좋은 방법이 무엇인지 궁금합니다. 이것이 내가 현재하고있는 방법이지만 더 나은 방법이 있어야한다고 생각합니다.

private static final byte[] CDRIVES = new byte[] { (byte)0xe0, 0x4f, (byte)0xd0,
    0x20, (byte)0xea, 0x3a, 0x69, 0x10, (byte)0xa2, (byte)0xd8, 0x08, 0x00, 0x2b,
    0x30, 0x30, (byte)0x9d };
private static final byte[] CMYDOCS = new byte[] { (byte)0xba, (byte)0x8a, 0x0d,
    0x45, 0x25, (byte)0xad, (byte)0xd0, 0x11, (byte)0x98, (byte)0xa8, 0x08, 0x00,
    0x36, 0x1b, 0x11, 0x03 };
private static final byte[] IEFRAME = new byte[] { (byte)0x80, 0x53, 0x1c,
    (byte)0x87, (byte)0xa0, 0x42, 0x69, 0x10, (byte)0xa2, (byte)0xea, 0x08,
    0x00, 0x2b, 0x30, 0x30, (byte)0x9d };
...
and so on

비효율적이지만 깨끗하게 보일 수있는 것이 있습니까? 예를 들면 다음과 같습니다.

private static final byte[] CDRIVES =
    new byte[] { "0xe04fd020ea3a6910a2d808002b30309d" };

답변:


111

에 헥사 문자열을 변환하는 기능을 사용하면 byte[], 당신은 할 수

byte[] CDRIVES = hexStringToByteArray("e04fd020ea3a6910a2d808002b30309d");

Dave L이 정의한 함수를 사용하는 것이 좋습니다. Java를 사용하여 16 진 덤프의 문자열 표현을 바이트 배열 변환 .

가독성을 극대화하기 위해 여기에 삽입합니다.

public static byte[] hexStringToByteArray(String s) {
    int len = s.length();
    byte[] data = new byte[len / 2];
    for (int i = 0; i < len; i += 2) {
        data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                             + Character.digit(s.charAt(i+1), 16));
    }
    return data;
}

CDRIVES static및 을 허용 final하면 성능 저하와 관련이 없습니다.


78
byte[] myvar = "Any String you want".getBytes();

문자열 리터럴을 이스케이프하여 모든 문자를 제공 할 수 있습니다.

byte[] CDRIVES = "\u00e0\u004f\u00d0\u0020\u00ea\u003a\u0069\u0010\u00a2\u00d8\u0008\u0000\u002b\u0030\u0030\u009d".getBytes();

50
포스터에서 원하는대로 문자열 "0000"을 (이진) {0x30,0x30,0x30,0x30}대신 (ASCII {0x00,0x00,0x00,0x00})로 바꾸지 않습니까?
jww

5
질문의 제목을보십시오. 그런 다음이 답변을 다시보십시오. 이제 말해봐, 무슨 일이야? 포스터의 특정 문제를 해결할 수는 없지만 확실하게 해결했습니다. 의사 난수 생성기의 시드로 사용하기 위해 문자열을 바이트 배열로 변환해야했고 이것은 매력처럼 작동했습니다.
e18r

@ e18r 바이트를 생성하고 있습니다. 그러나 기본 문자셋에 따라 달라지는 것을 알 수 없습니다. 최소한 .getBytes (desiredEncoding)를 사용하십시오.
quant

@petmez 바보 질문 : 자바에서 "".getBytes (UTF_8)); (빈 문자열의 getBytes) 안전한 작업? '법적'입니까? 아니면 그냥 할 수 있습니다 : = new byte [0]; ?
Robert Achmann

1
@RobertAchmann "".getbytes ( "UTF-8")는 빈 배열을 반환해야하며 완벽하게 합법적입니다.
재즈 피

33

Java 6에는 원하는 것을 정확하게 수행하는 방법이 있습니다.

private static final byte[] CDRIVES = javax.xml.bind.DatatypeConverter.parseHexBinary("e04fd020ea3a6910a2d808002b30309d")

또는 Google Guava를 사용할 수 있습니다 .

import com.google.common.io.BaseEncoding;
private static final byte[] CDRIVES = BaseEncoding.base16().lowerCase().decode("E04FD020ea3a6910a2d808002b30309d".toLowerCase());

작은 배열을 사용하면 Guava 방법이 과도합니다. 그러나 구아바에는 입력 스트림을 구문 분석 할 수있는 버전도 있습니다. 큰 16 진수 입력을 처리 할 때 유용한 기능입니다.


구아바 예제는 작성된대로 작동하지 않습니다 base16().lowerCase().decode(...). 16 진수 숫자가 소문자 여야 합니다. docs.guava-libraries.googlecode.com/git/javadoc/com/google/…
Peter DeGlopper

@PeterDeGlopper 좋은 발견, 나는 대답을 업데이트하여 코드가 이제 소문자와 대문자로 문자열을 처리합니다.
stefan.schwetschke

1
javax.xml.bindJava 9에서 슬프게도 제거되었습니다.
randomdude999

7

바이트 배열 대신 Java UUID 클래스를 사용하여 이러한 값을 저장할 수 있습니다.

UUID

public UUID(long mostSigBits,
            long leastSigBits)

지정된 데이터를 사용하여 새 UUID를 구성합니다. mostSigBits는 UUID의 최상위 64 비트에 사용되며 leastSigBits는 UUID의 최하위 64 비트가됩니다.


2

클린 프로세스에 관한 한 ByteArrayOutputStream 객체를 사용할 수 있습니다 ...

ByteArrayOutputStream bObj = new ByteArrayOutputStream();
bObj.reset();

// 다음을 사용하여 모든 값을 bObj에 하나씩 쓰기

bObj.write(byte value)

// 완료되면 다음을 사용하여 바이트를 얻을 수 있습니다.

CDRIVES = bObj.toByteArray();

// CMYDOCS 및 IEFRAME에 대해서도 유사한 프로세스를 반복 할 수 있기 때문에

참고 실제로 어레이가 작은 경우에는 효율적인 솔루션이 아닙니다.


2

라이브러리가없는 솔루션, 동적 길이가 반환 됨, 부호없는 정수 해석 (2의 보수가 아님)

    public static byte[] numToBytes(int num){
    if(num == 0){
        return new byte[]{};
    }else if(num < 256){
        return new byte[]{ (byte)(num) };
    }else if(num < 65536){
        return new byte[]{ (byte)(num >>> 8),(byte)num };
    }else if(num < 16777216){
        return new byte[]{ (byte)(num >>> 16),(byte)(num >>> 8),(byte)num };
    }else{ // up to 2,147,483,647
        return new byte[]{ (byte)(num >>> 24),(byte)(num >>> 16),(byte)(num >>> 8),(byte)num };
    }
}

1

이 상황에서 내가 선호하는 옵션 org.apache.commons.codec.binary.HexStringy 16 진과 2 진 사이를 변환하는 데 유용한 API가있는 것입니다 . 예를 들면 다음과 같습니다.

  1. Hex.decodeHex(char[] data)DecoderException배열에 16 진수가 아닌 문자가 있거나 홀수 개의 문자가 있으면를 던집니다 .

  2. Hex.encodeHex(byte[] data)는 위의 디코딩 방법에 대응하며 char[].

  3. Hex.encodeHexString(byte[] data)byte배열에서를 다시로 변환 합니다 String.

용법: Hex.decodeHex("dd645a2564cbe648c8336d2be5eafaa6".toCharArray())


1

이 유틸리티 기능을 사용할 수 있습니다 :

public static byte[] fromHexString(String src) {
    byte[] biBytes = new BigInteger("10" + src.replaceAll("\\s", ""), 16).toByteArray();
    return Arrays.copyOfRange(biBytes, 1, biBytes.length);
}

Denys Séguret 및 stefan.schwetschke의 변형과 달리 구분 기호 (공백, 탭 등)를 입력 문자열에 삽입하여 더 읽기 쉽습니다.

사용 예 :

private static final byte[] CDRIVES
    = fromHexString("e0 4f d0 20 ea 3a 69 10 a2 d8 08 00 2b 30 30 9d");
private static final byte[] CMYDOCS
    = fromHexString("BA8A0D4525ADD01198A80800361B1103");
private static final byte[] IEFRAME
    = fromHexString("80531c87 a0426910 a2ea0800 2b30309d");

1

컴파일시 헥사 번호로 할당 할 수있는 가장 작은 내부 형태이며, 문자 대로

private static final char[] CDRIVES_char = new char[] {0xe0, 0xf4, ...};

동등한 바이트 배열을 가지려면 다음과 같이 변환을 배포 할 수 있습니다

public static byte[] charToByteArray(char[] x)
{
    final byte[] res = new byte[x.length];
    for (int i = 0; i < x.length; i++)
    {
        res[i] = (byte) x[i];
    }
    return res;
}

public static byte[][] charToByteArray(char[][] x)
{
    final byte[][] res = new byte[x.length][];
    for (int i = 0; i < x.length; i++)
    {
        res[i] = charToByteArray(x[i]);
    }
    return res;
}

-2
private static final int[] CDRIVES = new int[] {0xe0, 0xf4, ...};

액세스 후 바이트로 변환합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.