java bytebuffer write read append
问题描述:
我试图使用ByteBuffer来解析我接收到的数据包作为字节数组,并可能包含部分或多个数据包。数据包的长度是可变的,所以我需要解析前两个字节来获取数据包的长度,并且似乎一旦我翻转()缓冲区来读取数据包,如果数据包不完整,我不能返回并追加更多的数据。java bytebuffer write read append
如何将数据写入缓冲区,读取其中的一些内容以验证内容,然后在保留读取数据的同时向其附加更多数据?
class Foo {
static final byte[] DATA1 = {0, 13, 2, 65, 88, 80, 55, 51, 52, 84, 82, 43, -111};
static final byte[] DATA2 = {0, 21, 6, 2, 3, 67, 23, 71, -77, 24, -66, -12, -76, 98, 25, 61, 54, -20, 127, -118, 71};
static final byte[] DATA3 = {0, 21, 5, 3, 5, 67};
static final byte[] DATA4 = {23, 72, -50, 24, -66, -9, -31, -86, 25, 61, -95, 75, 71, 47, -102, 0, 13, 2, 84};
static final byte[] DATA5 = {82, 65, 28, 10, 65, 71, 52, 44, 11};
ByteBuffer mByteBuffer = ByteBuffer.allocate(4096);
public void test() {
mByteBuffer.order(ByteOrder.BIG_ENDIAN);
parse(DATA1);
parse(DATA2);
parse(DATA3);
parse(DATA4);
parse(DATA5);
}
public void parse(byte[] bytes) {
short byteCount;
short crc;
mByteBuffer.put(bytes);
mByteBuffer.flip();
while (mByteBuffer.remaining() > 5) {
byteCount = mByteBuffer.getShort();
// check for invalid buffer
if (byteCount < 5) {
mByteBuffer.clear();
return;
}
if (mByteBuffer.remaining() < (byteCount - 2)) {
// TODO: incomplete packet, do something
}
// payload (u8[1 .. 4092])
byte[] payload = new byte[byteCount - 4];
mByteBuffer.get(payload, 0, payload.length);
// crc (u16)
crc = mByteBuffer.getShort();
}
mByteBuffer.clear();
}
}
答
呼叫compact()
的getShort()
后,或一般的任何序列的获取或写入后先下一read()
。
答
我在这里做了不少变动,他们都在评论中解释。
private final ByteBuffer mByteBufferAlloc = ByteBuffer.allocate(4096);
private ByteBuffer mByteBuffer = mByteBufferAlloc.duplicate(); // create a duplicate so we can use without affecting the original allocated buffer so we have a blank slate to reset to
public void test()
{
mByteBuffer.order(ByteOrder.BIG_ENDIAN);
parse(DATA1);
parse(DATA2);
parse(DATA3);
parse(DATA4);
parse(DATA5);
}
public void parse(byte[] bytes)
{
short byteCount;
short crc;
if(bytes.length > mByteBuffer.remaining()) // Ran out of room, compact anything not yet processed back to the beginning of the buffer and start back with a copy of the allocated buffer
{
int numBytes = mByteBuffer.position();
if(numBytes > 0)
{
byte[] toCompact = new byte[numBytes];
((ByteBuffer) mByteBuffer.flip()).get(toCompact);
mByteBuffer = mByteBufferAlloc.duplicate().put(toCompact);
}
else // nothing in the buffer, simply start fresh
mByteBuffer = mByteBufferAlloc.duplicate();
}
mByteBuffer.put(bytes);
mByteBuffer.flip();
while(mByteBuffer.remaining() > 5)
{
byteCount = mByteBuffer.getShort();
// check for invalid buffer
if(byteCount < 5)
{
System.err.println("Invalid data, throwing away buffer.");
mByteBuffer.clear(); // something was invalid, throw away the entire buffer, but we should probably log an error or something
return;
}
if(mByteBuffer.remaining() < (byteCount - 2))
{
// not enough data, wait for more
break;
}
// payload (u8[1 .. 4092])
byte[] payload = new byte[byteCount - 4];
mByteBuffer.get(payload, 0, payload.length);
// crc (u16)
crc = mByteBuffer.getShort();
int pos = mByteBuffer.position(), limit = mByteBuffer.limit(), capacity = mByteBuffer.capacity();
mByteBuffer = ((ByteBuffer) mByteBuffer.limit(capacity)).slice();
mByteBuffer.limit(limit - pos); // cut the packet off the beginning so we won't parse it again
// TODO do something with the packet
}
mByteBuffer.position(mByteBuffer.limit()).limit(mByteBuffer.capacity()); // reset the position to the end of the added data and the limit to the capacity
// mByteBuffer.clear(); Don't want to do this because we want the next call to append to the buffer so retain state
}
不会'compact()'删除我已经读过的任何数据,比如我正在偷看的字节数,看看我是否有一个完整的数据包? – jmfox24