この文書化された解決策 ここ はまだ解決策ですか、それとも4バイトからintを取得する他の方法はありますか?
ありがとうございました。
編集:ソケットからbyte []を取得しています。
編集:int recvMsgSize = in.read(Data, 0, BufferSize);
recvMsgSizeが-1の場合、接続が切断されたことがわかります。
inputStreamの代わりにDataInputStreamを使用しているときにこれを検出するにはどうすればよいですか?
ありがとう。
編集:正しい答えを受け入れることに関してヨーヨーであることをお詫びします。しかし、mihiの更新された最終応答の後、メソッドはしっかりしていて、拡張コーディングを削減しているように見えます。私の意見では、ベストプラクティスです。
これらの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)
もちろん手動で行うこともできますが、ほとんどの場合、それらの1つを使用する方が簡単です(たとえば、多数のバイトを含むバイト配列を変換する必要がある場合は、DataInputStream
の周りにByteArrayInputStream
を使用することをお勧めします)。
Edit:エンディアンを変更する必要がある場合は、ByteBufferを使用するか、バイトを自分で反転するか、DataInputとして自分で変換する必要があります。エンディアンの変更はサポートしていません。
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:ストリームから複数回読み取る場合、停止した場所から読み取りを続行します。 e。 aByteはバイト0、anIntはバイト1〜4、anotherIntはバイト5〜8などになります。readFullyはその後読み取りを行い、lotOfbytes
を読み取るまでブロックします。
ストリームが停止すると(接続が切断されると)、-1ではなくEOFException
が取得されるため、-1を取得すると、intは実際には-1になります。
バイトをまったく解析したくない場合は、それらをスキップ()できます。 DataInputStreamでは1バイトを2つの異なる方法で解析することはできません(つまり、最初にバイト0から3のintを読み取り、次にバイト2から5のintを読み取ります)が、通常は必要ありません。
例:
// 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.
これがあなたの追加の質問に答えることを願っています。
拡大変換と数値昇格には細心の注意を払う必要がありますが、以下のコードは4byte
をint
に変換します。
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"
& 0xFF
でマスクする必要性に注意してください-すべての算術演算はbyte
(またはint
)に昇格するため、long
を使用している場合は、おそらくこれを多く行うことになります。それらがすでにbyte[]
配列にある場合は、次を使用できます。
int result = ByteBuffer.wrap(bytes).getInt();
または、クラスパスにGoogleの guava-libraries がある場合は、ショートカットがあります。
int result = Ints.fromByteArray(array);
これには、他のタイプ(Longs.fromByteArray
、Shorts.fromByteArray
など)にも同様に優れたAPIがあるという利点があります。