web-dev-qa-db-ja.com

Javaでバイト配列を整数に変換します。

私はいくつかのデータをJavaのバイト配列に格納したいです。基本的に単なる数字で、数字あたり最大2バイトかかります。

整数を2バイト長のバイト配列に、またはその逆に変換する方法を知りたいのですが。私はたくさんの解決策をグーグルで見つけましたが、それらのほとんどはコードで何が起こるのか説明していません。私は本当に理解していないことをシフトするものがたくさんありますので、私は基本的な説明をいただければ幸いです。

121
Chris

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 }
201
Jeff Mercado
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
int fromByteArray(byte[] bytes) {
     return bytes[0] << 24 | (bytes[1] & 0xFF) << 16 | (bytes[2] & 0xFF) << 8 | (bytes[3] & 0xFF);
}

符号付きバイトをint型にパックするとき、算術昇格規則(JLS、変換および昇格で説明されている)のために各バイトは32ビットに符号拡張される(ゼロ拡張ではなく)ため、マスクオフする必要があります。

これに関連した面白いパズルがJoshua BlochとNeal GafterによるJava Puzzlers( "1バイトごとの大きな喜び")で説明されています。 byte値を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
}

Charが16ビット符号なし整数型であることを除いて、すべての数値型はJavaで符号付きです。

116

可変長バイトにBigIntegerを使用することもできます。あなたはlong、int、shortのどちらにも変換できます。

new BigInteger(bytes).intValue();

または極性を示すために:

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

バイトを取り戻すには:

new BigInteger(bytes).toByteArray()
46
Jamel Toms

基本的な実装は次のようになります。

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://ja.wikipedia.org/wiki/Endianness

上記のソースコードは34 12 78 56 bc 9aを出力します。最初の2バイト(34 12)は最初の整数などを表します。上記のソースコードは整数をリトルエンディアン形式でエンコードします。

5
prekageo
/** 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;
    }
1
Dhaval Rami

彼らがビットから読まなければならないという要件を持つ誰かは、あなたがたった3ビットから読まなければならないと言うことができます、しかし、あなたは以下を使う符号付き整数を必要とします:

data is of type: Java.util.BitSet

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

マジックナンバー3はあなたが使っているビット(バイトではない)の数に置き換えることができます。

0
Vishrant