Code Bye

求个byte数据处理方案,谢谢

 

蓝牙实时收到一系列有规则数据。如下
55 AA 81 01   5C    00 0C     31 02        FF 01 00 0B     00 04     41 46 66 66
55 AA 81 01  =  数据头
5C  = 效验位
00 0C = 数据长度
31 02 = 数据命令字
FF 01 00 0B = 某一项数据的ID
00 04 = 某一项数据的长度
41 46 66 66 = 某一项数据的值(IEEE-754格式的单精度4字节浮点数)

Android的蓝牙串口接收不知道怎么像Windows一样指定接收字节数。
所以现在的想法是,被动的全部接收,然后存在一个大的缓冲区里,开个线程处理读取缓冲区,处理。

但是对java的字节处理也不懂。所以求一个byte字节的先进先出解决算法。谢谢


39分
有个ByteArrayOutputStream可能可以用,不断把byte[]通过write写入缓冲区,最后调用toByteArray获取全部byte[]。
缺点是不能取出指定的字节数。
不过我觉得自己写一个也不麻烦,没有几行代码。
代码大概是下面这样的,我没有测试过:
public class BytesBuffer {
	private byte[] buffer = new byte[4096];
	private int head;
	private int tail;

	public void push(byte[] data, int start, int length) {
		int free = buffer.length - tail;
		if (free < data.length) {
			int used = tail - head;
			if (head + free >= data.length) {
				System.arraycopy(buffer, head, buffer, 0, used);
			} else {
				int size = buffer.length * 2;
				int want = used + data.length;
				while (size < want) {
					size += size;
				}
				byte[] block = new byte[size];
				System.arraycopy(buffer, head, block, 0, used);
				buffer = block;
			}
			tail = used;
			head = 0;
		}
		System.arraycopy(data, start, buffer, tail, length);
		tail += data.length;
	}

	public void push(byte[] data) {
		push(data, 0, data.length);
	}

	public int pop(byte[] data, int start, int length) {
		int used = tail - head;
		if (used == 0)
			return 0;
		int size = used;
		if (size > length) {
			size = length;
		}
		System.arraycopy(buffer, head, data, start, size);
		head += size;
		if (head == tail) {
			head = 0;
			tail = 0;
		}
		return size;
	}

	public int pop(byte[] data) {
		return pop(data, 0, data.length);
	}
}
上面的代码有些错误,更正如下:
public class BytesBuffer {
	private byte[] buffer = new byte[4096];
	private int head;
	private int tail;

	public void push(byte[] data, int start, int length) {
		int free = buffer.length - tail;
		if (free < length) {
			int used = tail - head;
			if (head + free >= length) {
				System.arraycopy(buffer, head, buffer, 0, used);
			} else {
				int size = buffer.length * 2;
				int want = used + length;
				while (size < want) {
					size += size;
				}
				byte[] block = new byte[size];
				System.arraycopy(buffer, head, block, 0, used);
				buffer = block;
			}
			tail = used;
			head = 0;
		}
		System.arraycopy(data, start, buffer, tail, length);
		tail += data.length;
	}

	public void push(byte[] data) {
		push(data, 0, data.length);
	}

	public int pop(byte[] data, int start, int length) {
		int used = tail - head;
		if (used == 0)
			return 0;
		int size = used;
		if (size > length) {
			size = length;
		}
		System.arraycopy(buffer, head, data, start, size);
		head += size;
		if (head == tail) {
			head = 0;
			tail = 0;
		}
		return size;
	}

	public int pop(byte[] data) {
		return pop(data, 0, data.length);
	}
}
用小号顶一下
上面的还是有些错误,现在应该没问题了
public class BytesBuffer {
	private byte[] buffer = new byte[4096];
	private int head;
	private int tail;

	public void push(byte[] data, int start, int length) {
		int free = buffer.length - tail;
		if (free < length) {
			int used = tail - head;
			if (head + free >= length) {
				System.arraycopy(buffer, head, buffer, 0, used);
			} else {
				int size = buffer.length * 2;
				int want = used + length;
				while (size < want) {
					size += size;
				}
				byte[] block = new byte[size];
				System.arraycopy(buffer, head, block, 0, used);
				buffer = block;
			}
			tail = used;
			head = 0;
		}
		System.arraycopy(data, start, buffer, tail, length);
		tail += length;
	}

	public void push(byte[] data) {
		push(data, 0, data.length);
	}

	public int pop(byte[] data, int start, int length) {
		int used = tail - head;
		if (used == 0)
			return 0;
		int size = used;
		if (size > length) {
			size = length;
		}
		System.arraycopy(buffer, head, data, start, size);
		head += size;
		if (head == tail) {
			head = 0;
			tail = 0;
		}
		return size;
	}

	public int pop(byte[] data) {
		return pop(data, 0, data.length);
	}
}
引用 6 楼 hjq2013 的回复:
引用 5 楼 svenwang 的回复:

上面的还是有些错误,现在应该没问题了

public class BytesBuffer {
	private byte[] buffer = new byte[4096];
	private int head;
	private int tail;

	public void push(byte[] data, int start, int length) {
		int free = buffer.length - tail;
		if (free < length) {
			int used = tail - head;
			if (head + free >= length) {
				System.arraycopy(buffer, head, buffer, 0, used);
			} else {
				int size = buffer.length * 2;
				int want = used + length;
				while (size < want) {
					size += size;
				}
				byte[] block = new byte[size];
				System.arraycopy(buffer, head, block, 0, used);
				buffer = block;
			}
			tail = used;
			head = 0;
		}
		System.arraycopy(data, start, buffer, tail, length);
		tail += length;
	}

	public void push(byte[] data) {
		push(data, 0, data.length);
	}

	public int pop(byte[] data, int start, int length) {
		int used = tail - head;
		if (used == 0)
			return 0;
		int size = used;
		if (size > length) {
			size = length;
		}
		System.arraycopy(buffer, head, data, start, size);
		head += size;
		if (head == tail) {
			head = 0;
			tail = 0;
		}
		return size;
	}

	public int pop(byte[] data) {
		return pop(data, 0, data.length);
	}
}

非常感谢啊,马上试用一下

引用 5 楼 svenwang 的回复:

上面的还是有些错误,现在应该没问题了

public class BytesBuffer {
	private byte[] buffer = new byte[4096];
	private int head;
	private int tail;

	public void push(byte[] data, int start, int length) {
		int free = buffer.length - tail;
		if (free < length) {
			int used = tail - head;
			if (head + free >= length) {
				System.arraycopy(buffer, head, buffer, 0, used);
			} else {
				int size = buffer.length * 2;
				int want = used + length;
				while (size < want) {
					size += size;
				}
				byte[] block = new byte[size];
				System.arraycopy(buffer, head, block, 0, used);
				buffer = block;
			}
			tail = used;
			head = 0;
		}
		System.arraycopy(data, start, buffer, tail, length);
		tail += length;
	}

	public void push(byte[] data) {
		push(data, 0, data.length);
	}

	public int pop(byte[] data, int start, int length) {
		int used = tail - head;
		if (used == 0)
			return 0;
		int size = used;
		if (size > length) {
			size = length;
		}
		System.arraycopy(buffer, head, data, start, size);
		head += size;
		if (head == tail) {
			head = 0;
			tail = 0;
		}
		return size;
	}

	public int pop(byte[] data) {
		return pop(data, 0, data.length);
	}
}

测试中发现一个问题,我用Read到byte数值中的值有负数,蓝牙传过来的是0-FF的值,而byte的MAX_VALUE只有0x7F
无法比较值。有什么好的办法呢?

                                       //验证字节头 必须是 55 AA 81 01才为有效返回
					mBytesBuffer.pop(bHead, 0, 1);
					if(bHead[0] != 0x55)
						continue;
					mBytesBuffer.pop(bHead, 1, 1);
					if(bHead[1] != 0xAA)
						continue;
					mBytesBuffer.pop(bHead, 2, 1);
					if(bHead[1] != 0x81)
						continue;
					mBytesBuffer.pop(bHead, 3, 1);
					if(bHead[1] != 0x01)
						continue;
					//获取其他数据
					 mBytesBuffer.pop(bCheck, 4, 1);
					 mBytesBuffer.pop(bLen, 5, 2);
					 mBytesBuffer.pop(bCmd, 7, 4);
					 mBytesBuffer.pop(bDsID, 11, 4);
					 mBytesBuffer.pop(bDsValueType, 15, 1);
					 mBytesBuffer.pop(bDsValueLen, 16, 2);
					 iValueDataLen = bDsValueLen[0]*0x100 + bDsValueLen[1];
					 bDsValueData = new byte[iValueDataLen];
					 mBytesBuffer.pop(bDsValueData, 18, iValueDataLen);
引用 9 楼 hnicypb 的回复:
Quote: 引用 5 楼 svenwang 的回复:

上面的还是有些错误,现在应该没问题了

public class BytesBuffer {
	private byte[] buffer = new byte[4096];
	private int head;
	private int tail;

	public void push(byte[] data, int start, int length) {
		int free = buffer.length - tail;
		if (free < length) {
			int used = tail - head;
			if (head + free >= length) {
				System.arraycopy(buffer, head, buffer, 0, used);
			} else {
				int size = buffer.length * 2;
				int want = used + length;
				while (size < want) {
					size += size;
				}
				byte[] block = new byte[size];
				System.arraycopy(buffer, head, block, 0, used);
				buffer = block;
			}
			tail = used;
			head = 0;
		}
		System.arraycopy(data, start, buffer, tail, length);
		tail += length;
	}

	public void push(byte[] data) {
		push(data, 0, data.length);
	}

	public int pop(byte[] data, int start, int length) {
		int used = tail - head;
		if (used == 0)
			return 0;
		int size = used;
		if (size > length) {
			size = length;
		}
		System.arraycopy(buffer, head, data, start, size);
		head += size;
		if (head == tail) {
			head = 0;
			tail = 0;
		}
		return size;
	}

	public int pop(byte[] data) {
		return pop(data, 0, data.length);
	}
}

测试中发现一个问题,我用Read到byte数值中的值有负数,蓝牙传过来的是0-FF的值,而byte的MAX_VALUE只有0x7F
无法比较值。有什么好的办法呢?

                                       //验证字节头 必须是 55 AA 81 01才为有效返回
					mBytesBuffer.pop(bHead, 0, 1);
					if(bHead[0] != 0x55)
						continue;
					mBytesBuffer.pop(bHead, 1, 1);
					if(bHead[1] != 0xAA)
						continue;
					mBytesBuffer.pop(bHead, 2, 1);
					if(bHead[1] != 0x81)
						continue;
					mBytesBuffer.pop(bHead, 3, 1);
					if(bHead[1] != 0x01)
						continue;
					//获取其他数据
					 mBytesBuffer.pop(bCheck, 4, 1);
					 mBytesBuffer.pop(bLen, 5, 2);
					 mBytesBuffer.pop(bCmd, 7, 4);
					 mBytesBuffer.pop(bDsID, 11, 4);
					 mBytesBuffer.pop(bDsValueType, 15, 1);
					 mBytesBuffer.pop(bDsValueLen, 16, 2);
					 iValueDataLen = bDsValueLen[0]*0x100 + bDsValueLen[1];
					 bDsValueData = new byte[iValueDataLen];
					 mBytesBuffer.pop(bDsValueData, 18, iValueDataLen);

java的byte是有符号的(我觉得是很糟糕的设计),所以只好先转成int再比较:

if ((bHead[1] & 0xff) != 0x81)
	continue;
引用 10 楼 svenwang 的回复:
Quote: 引用 9 楼 hnicypb 的回复:
Quote: 引用 5 楼 svenwang 的回复:

上面的还是有些错误,现在应该没问题了

public class BytesBuffer {
	private byte[] buffer = new byte[4096];
	private int head;
	private int tail;

	public void push(byte[] data, int start, int length) {
		int free = buffer.length - tail;
		if (free < length) {
			int used = tail - head;
			if (head + free >= length) {
				System.arraycopy(buffer, head, buffer, 0, used);
			} else {
				int size = buffer.length * 2;
				int want = used + length;
				while (size < want) {
					size += size;
				}
				byte[] block = new byte[size];
				System.arraycopy(buffer, head, block, 0, used);
				buffer = block;
			}
			tail = used;
			head = 0;
		}
		System.arraycopy(data, start, buffer, tail, length);
		tail += length;
	}

	public void push(byte[] data) {
		push(data, 0, data.length);
	}

	public int pop(byte[] data, int start, int length) {
		int used = tail - head;
		if (used == 0)
			return 0;
		int size = used;
		if (size > length) {
			size = length;
		}
		System.arraycopy(buffer, head, data, start, size);
		head += size;
		if (head == tail) {
			head = 0;
			tail = 0;
		}
		return size;
	}

	public int pop(byte[] data) {
		return pop(data, 0, data.length);
	}
}

测试中发现一个问题,我用Read到byte数值中的值有负数,蓝牙传过来的是0-FF的值,而byte的MAX_VALUE只有0x7F
无法比较值。有什么好的办法呢?

                                       //验证字节头 必须是 55 AA 81 01才为有效返回
					mBytesBuffer.pop(bHead, 0, 1);
					if(bHead[0] != 0x55)
						continue;
					mBytesBuffer.pop(bHead, 1, 1);
					if(bHead[1] != 0xAA)
						continue;
					mBytesBuffer.pop(bHead, 2, 1);
					if(bHead[1] != 0x81)
						continue;
					mBytesBuffer.pop(bHead, 3, 1);
					if(bHead[1] != 0x01)
						continue;
					//获取其他数据
					 mBytesBuffer.pop(bCheck, 4, 1);
					 mBytesBuffer.pop(bLen, 5, 2);
					 mBytesBuffer.pop(bCmd, 7, 4);
					 mBytesBuffer.pop(bDsID, 11, 4);
					 mBytesBuffer.pop(bDsValueType, 15, 1);
					 mBytesBuffer.pop(bDsValueLen, 16, 2);
					 iValueDataLen = bDsValueLen[0]*0x100 + bDsValueLen[1];
					 bDsValueData = new byte[iValueDataLen];
					 mBytesBuffer.pop(bDsValueData, 18, iValueDataLen);

java的byte是有符号的(我觉得是很糟糕的设计),所以只好先转成int再比较:

if ((bHead[1] & 0xff) != 0x81)
	continue;

有效,谢了。我继续研究,这个先给分。


CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明求个byte数据处理方案,谢谢