14

ここに記載されているこの解決策がまだ解決策であるかどうか、または4バイトからintを取得する他の方法があるかどうか疑問に思っていましたか?

ありがとうございました。

編集: ソケット .read から byte[] を取得しています

編集: int recvMsgSize = in.read(Data, 0, BufferSize);recvMsgSize が -1 の場合、接続が切断されたことがわかります。

InputStream の代わりに DataInputStream を使用しているときにこれを検出するにはどうすればよいですか?

ありがとう。

編集:正しい答えを受け入れることに関してヨーヨーであることをお詫びします。しかし、mihi の更新された最終的な応答の後、この方法はしっかりしていて、拡張コーディングを削減しているように見えます。私の意見では、ベスト プラクティスです。

4

5 に答える 5

20

拡大変換と数値昇格には細心の注意を払う必要がありますが、以下のコードは 4 を に変換byteintます。

    byte b1 = -1;
    byte b2 = -2;
    byte b3 = -3;
    byte b4 = -4;
    int i = ((0xFF & b1) << 24) | ((0xFF & b2) << 16) |
            ((0xFF & b3) << 8) | (0xFF & b4);
    System.out.println(Integer.toHexString(i)); // prints "fffefdfc"

こちらもご覧ください

于 2010-05-15T13:16:49.620 に答える
19

それらがすでにbyte[]配列にある場合は、次を使用できます。

int result = ByteBuffer.wrap(bytes).getInt();

または、クラスパスに Google のguava-librariesがある場合は、次のショートカットがあります。

int result = Ints.fromByteArray(array);

Longs.fromByteArrayこれには、他のタイプ ( 、Shorts.fromByteArrayなど)に対しても同様に優れた API があるという利点があります。

于 2010-05-15T13:51:12.630 に答える
8

これらの 4 バイトをどこから取得するかによって、次のようになります。

http://docs.oracle.com/javase/7/docs/api/java/io/DataInput.html#readInt()

http://docs.oracle.com/javase/7/docs/api/java/nio/ByteBuffer.html#getInt(int)

もちろん、手動で行うこともできますが、ほとんどの場合、これらのいずれかを使用する方が簡単です (多数のバイトを含むバイト配列を変換する必要がある場合は、たとえばa のDataInputStream周りに aを使用することをお勧めします)。ByteArrayInputStream

編集: エンディアンを変更する必要がある場合は、DataInput がエンディアンの変更をサポートしていないため、ByteBuffer を使用するか、自分でバイトを逆にするか、自分で変換する必要があります。

Edit2 :ソケット入力ストリームからそれらを取得すると、それをラップして、DataInputStreamあらゆる種類のデータを読み取るために使用します。特に InputStream.read(byte[]) はバイト配列全体を埋めることを保証しないので... DataInputStream.readFully はそうします。

DataInputStream in = new DataInputStream(socket.getInputStream());
byte aByte = in.readByte();
int anInt = in.readInt();
int anotherInt = in.readInt();
short andAShort = in.readShort(); // 11 bytes read :-)
byte[] lotOfBytes = new byte[anInt];
in.readFully(lotOfBytes);

Edit3 : ストリームから複数回読み取る場合、停止した場所から読み取りを続行します。つまり、aByte はバイト 0、anInt はバイト 1 から 4、anotherInt はバイト 5 から 8 などになります。読み取りが完了するまでブロックしますlotOfbytes

ストリームが停止する (接続が切断される) とEOFException、-1 の代わりに取得されるため、-1 を取得すると、int は実際には -1 でした。

バイトをまったく解析したくない場合は、skip() できます。1 バイトを 2 つの異なる方法で解析することは DataInputStream では不可能ですが (つまり、最初にバイト 0 から 3 までの int を読み取り、次にバイト 2 から 5 までを 1 つ読み取ります)、通常はどちらも必要ありません。

例:

// read messages (length + data) until the stream ends:
while (true) {
int messageLength;
try {
    messageLength = in.readInt(); // bytes 0 to 3
} catch (EOFException ex) {
    // connection dropped, so handle it, for example
    return;
}
byte[] message = new byte[messageLength];
in.readFully(message);
// do something with the message.
}
// all messages handled.

これがあなたの追加の質問に答えることを願っています.

于 2010-05-15T13:09:26.937 に答える
-1

機能的なスタイルのソリューション(多様性のためだけに、使用にはあまり便利ではありません):

private int addByte (int base, byte appendix) {
    return (base << 4) + appendix;
}

public void test() {
    byte b1 = 5, b2 = 5, byte b3 = 0, b4 = 1;
    int result = addByte (addByte (addByte (addByte (0, b1), b2), b3), b4);
}
于 2010-05-15T13:34:04.583 に答える
-3

mihi が言ったように、これらのバイトをどこから取得しているかによって異なりますが、次のコードが役立つ場合があります。

int myNumber = (((int)byteOne) << 0) |
    (((int)byteTwo) << 8) |
    (((int)byteThree) << 16) |
    (((int)byteFour) << 24);
于 2010-05-15T13:20:33.500 に答える