我在java中寻找一种方法,从输入流中提取某些字节。 例如 我将有这个数据流出现
0x01,0x02,0x00,0x01,0x00,0x01,0x03,0x04,0x00,0x01,0x09,0x08,0x00,0x01,0x00,0x01
我的编码方案是类型数据结束
首先,我将检查第一个字节,
然后我想将所有数据存储在0x01的字节数组中,直到0x00,0x01,0x00,0x01
的出现,除了0x01
所以我将放入数组的第一段数据
0x01,0x02,0x00,0x00
然后到下一个,
这以0x03
开头,以0x00,0x01,0x00,0x01
结尾
我希望将其放在另一个字节数组中,
0x03,0x04,0x00,0x01,0x09,0x08,0x00,0x00
我将如何做到这一点,我开始使用
ByteArrayOutputStream动态添加到字节数组,无需知道大小, 但我失去了关于如何提取每个模式并删除0x00后的每个0x01的逻辑, 我也从输入流中输入一个字节,一次一个字节(这是我可以得到字节的唯一方法)
答案 0 :(得分:3)
你需要一个有限状态识别器。对于您的简单语法,以下伪代码应该可以解决这个问题:
state = 0;
while( (byte=input.read()) != EOF)
{
switch(state)
{
case 0: // "normal" state
if (byte == 0x00)
{
state = 1;
buf.append(byte);
}
else
output.write(byte)
break;
case 1: // We've seen a 0x00
if (byte == 0x00)
{
state = 1;
output.write(buf);
}
else if (byte == 0x01)
{
state = 2;
buf.append(byte);
}
else
{
output.write(buf);
buf.clear();
state = 0;
}
break;
case 2: // We've seen 0x00,0x01
if (byte == 0x00)
{
state = 3;
buf.append(byte);
}
else if (byte == 0x01)
{
output.write(0x00);
buf.clear();
state = 0;
}
else
{
output.write(buf);
buf.clear();
state = 0;
}
break;
case 3: // We've seen 0x00,0x01,0x00
if (byte == 0x00)
{
state = 1;
output.write(buf);
buf.clear();
buf.append(byte);
}
else if (byte == 0x01)
{
// The last four input bytes were 0x00,0x01,0x00,0x01
state = 0;
output.write(0x00,0x00);
buf.clear
}
else
{
output.write(buf);
buf.clear();
state = 0;
}
break;
}
}
if (!buf.empty()) output.write(buf);
这通过一次读取一个字节来工作。
如果它检测到0x00,我们需要开始寻找分隔符模式但保存字节以防以后我们发现这是一个误报警。 “状态”变量跟踪到目前为止我们所看到的内容。在每个点,如果输入匹配下一个预期的分隔符字节,我们保存它,碰撞状态并继续。如果在任何时候我们没有得到下一个预期的分隔符字节,我们只写出所有保存的数据,清除缓冲区并返回“正常”状态。但是,如果我们最终看到整个分隔符字符串,我们会写出0x00,0x00并丢弃保存的字节(这将是0x00,0x01,0x00,0x01)。
编辑:修改代码以处理来自OP的附加条件和来自@Shaded的评论