1

私が使用しているプロトコルでは、ファイル内の現在の位置を「ネットワーク バイト順の符号なしの 4 バイト整数」として送り返す必要があります。これにはいくつかの質問がありますが、Long ではなく Integ を使用していると仮定しています。

これを NIO の ByteBuffer に移植して、ソケット チャネルで送信できるようにしようとしています。

long bytesTransfered = ... some number of bytes transfered...
//TODO: What does this actually do?
outBuffer[0] = (byte) ((bytesTransfered >> 24) & 0xff);
outBuffer[1] = (byte) ((bytesTransfered >> 16) & 0xff);
outBuffer[2] = (byte) ((bytesTransfered >> 8) & 0xff);
//TODO: Why does netbeans say this does nothing?
outBuffer[3] = (byte) ((bytesTransfered >> 0) & 0xff);

これを達成する ByteBuffer のメソッドはありますか? うまくいけば、上記のビットシフトの魔法よりも、より明白で自己記述的な方法でしょうか?

4

2 に答える 2

6

符号付きか符号なしかにかかわらず、ビットは同じです。

longaを anにキャストするとint、JVM は上位ビットを破棄します。問題は、 を にプロモートするときに発生しintますlong。Java は値を符号拡張し、 のlong上位ビットを の最上位ビットで埋めintます。

この問題を解決するには、long にマスクを適用するだけです。以下は、これを明確にする必要があります。

long value = Integer.MAX_VALUE + 1234L;
System.out.println("original value    = " + value);

int iValue = (int)value;
System.out.println("value as int      = " + iValue);
byte[] array = new byte[4];

ByteBuffer buf = ByteBuffer.wrap(array);
buf.putInt(0, iValue);

int iRetrieved = buf.getInt(0);
System.out.println("int from buf      = " + iRetrieved);

long retrieved = iRetrieved;
System.out.println("converted to long = " + retrieved);

retrieved = retrieved & 0xFFFFFFFFL;
System.out.println("high bytes masked = " + retrieved);

ただし、まだ 32 ビットしかないことに注意してください。ファイルサイズが 4Gb より大きい場合、4 バイトに収まりません (2G を超えるファイルについて心配する必要がある場合は、4G を超えるファイルについて心配する必要があります)。

于 2013-05-22T19:46:32.300 に答える
3

まさにそのByteBuffer.putInt()ためです。あなたは使用していると言いますがlong、4バイトだけを書きたいので、 to にキャストする必要がありlongますint。またはputLong()、8バイトを使用して取得します。

于 2013-05-22T01:46:45.970 に答える