Javaでバイト配列を初期化するにはどうすればよいですか?


138

私はいくつかの定数値(UUID)をJavaのバイト配列形式で格納する必要があり、これらの静的配列を初期化する最善の方法は何だろうと思います。これが現在のやり方ですが、もっと良い方法があるはずだと感じています。

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");

Javaを使用して16進ダンプの文字列表現をバイト配列変換するで Dave Lによって定義された関数を使用することをお勧めしますか?

読みやすくするためにここに挿入します。

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 2014

5
質問のタイトルを見てください。次に、この答えを振り返ります。教えてください、何が悪いのですか?それはポスターの特定の問題を解決しないかもしれませんが、それは確かに私のものを解決しました。文字列をバイト配列に変換して、疑似乱数ジェネレータのシードとして使用する必要があり、これは魅力のように機能しました。
e18r

@ e18rはい、バイトを生成していますが、このデフォルトの文字セットに依存しているため、どちらを使用しているかはわかりません。少なくとも.getBytes(desiredEncoding)を使用してください。
定量

@petmezばかげた質問:JAVAでは、 ""。getBytes(UTF_8));のようなものです。(空の文字列のgetBytes)安全に行うには?それは「合法」ですか?または、次のようにすることもできます:= new byte [0]; ?
Robert Achmann

1
@RobertAchmann "" .getbytes( "UTF-8")は空の配列を返す必要があり、完全に合法です。
Jazzepi

33

Java 6には、希望どおりの処理を行うメソッドがあります。

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

あるいは、グアバを使用することができます:

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

小さな配列を使用している場合、Guavaメソッドはやりすぎです。しかし、Guavaには、入力ストリームを解析できるバージョンもあります。これは、大きな16進入力を処理するときに便利な機能です。


Guavaの例は、書かれているとおりに機能しませんbase16().lowerCase().decode(...)。小文字の16進数字がある場合に必要です。docs.guava-libraries.googlecode.com/git/javadoc/com/google/...
ピーターDeGlopper

@PeterDeGlopper良い結果です。答えを更新し、コードで小文字と大文字の両方の文字列を処理できるようにしました。
stefan.schwetschke 2015

1
javax.xml.bind悲しいことのJava 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();

//すべての値を1つずつbObjに書き込みます

bObj.write(byte value)

//完了したら、byte []を使用して取得できます

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 hexとバイナリ間の変換に役立つAPI を使用することです。例えば:

  1. Hex.decodeHex(char[] data)DecoderException配列に16進数以外の文字がある場合、または文字数が奇数の場合は、aをスローします。

  2. Hex.encodeHex(byte[] data)上記のdecodeメソッドに対応し、を吐き出し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);
}

DenysSé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

コンパイル時に16進数で割り当てることができる最小の内部型はcharです

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.