符号なし 32 ビット整数のリトル エンディアン エンコーディングである 4 バイトを読み取り、その値を Java int に割り当てたい
(はい、実際には「long」を使用しますが、この場合、unsigned 値が 2 の補数表記で signed int をオーバーフローするほど大きくなることは決してないことを「知っています」。 )。
問題の 4 バイトは、値「216」をリトルエンディアン スタイルでエンコードします。
0xD8000000
基本的には、次のビット パターンを Java int に詰め込むだけです。
0x000000D8
次の単純なコードでそれを行う必要があります...そして最初の 3 つの '0x00' バイトでは成功します:
byte b1 = din.readByte();
byte b2 = din.readByte();
byte b3 = din.readByte();
byte b4 = din.readByte();
int s = 0;
s = s | b4;
s = (s << 8);
s = s | b3;
s = (s << 8);
s = s | b2;
s = (s << 8);
s = s | b1;
return s;
ただし、次の点で失敗します。
s = s | b1;
... b1 のビットが 1101 1000 であるため、最上位ビットが 1 であるため、これは 2 の補数表記の負の数 (-40) です。 、-40 は 0xFFFFFFD8 としてエンコードされます。これにより、拡大された int の最初の 3 バイトが 0 になるという単純な仮定がねじれます。
だから私の戦略は行き詰まる。しかし、代わりに何をすべきですか?プリミティブ演算子を使用してこれを解決することは可能ですか (解決策を教えてください)、またはクラス ライブラリに頼る必要がありますか? (通常のコーディングではビットとバイトを直接いじることはあまりないので、「日常的な」コードであるべきと思われるものの慣用句が不足しています)。
クラス ライブラリのアプローチに関しては、次のフラグメントで正しい結果が得られます。
ByteBuffer b = ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).put((byte) 0xD8).put((byte) 0x00).put((byte) 0x00).put((byte) 0x00);
b.flip();
int s = b.getInt();
...読みやすさには問題ありませんが、省略したい8つのメソッド呼び出しを使用しています。
ありがとう!デビッド。