我正在尝试编写一个简单的管道和过滤器系统,我目前正在一次解析一个字节的输入流。
我的数据流遵循以下格式:
ID (4 字节) 数据 (8 字节) ID (4 字节)数据 (8 字节)
每个数据帧都有 6 对 ID 和数据。
解析此类流的最佳实践是什么?我希望能够过滤掉 id 和一些数据,这样我就会有一个只包含 DATA01、DATA02 等的表。
例如,我如何提取第一个id(例如000,整数)之后的第一个数据点(long),然后在第二个id(001,整数)之后提取第二个数据点(双精度)。
我希望我能够详细说明我的问题。
提前感谢您和问候,
菲利普
试试preon。有关简单示例,请参阅此链接。
如果您不想使用库,那么 DataInputStream 非常适合您的用例。有关示例,请参阅此链接。
是一个很好的类,用于完成你正在尝试做的事情。 ByteBuffer允许您直接将字节数组转换为其相应的原始值。这与读取缓冲区而不是一次读取一个字节相结合,您将获得相对简洁有效的解决方案!
例:
public void parseStream( InputStream is ) throws IOException
{
boolean vtoggle = true; // Are we converting to long or double?
ByteBuffer idBuffer = ByteBuffer.allocate( 4 ); // Initialize our id buffer
ByteBuffer valueBuffer = ByteBuffer.allocate( 8 ); // Initialize our value buffer
while( true /*or some real condition*/ )
{
idBuffer.put( readFromInput( is, 4 ) ); // Store the id bytes
valueBuffer.put( readFromInput( is, 8 ) ); // Store the value bytes
int id = idBuffer.getInt(); // Convert id bytes
if( vtoggle )
{
long lvalue = valueBuffer.getLong(); // Convert long bytes
// Do something with value
}
else
{
double dvalue = valueBuffer.getDouble(); // Convert double bytes
// Do something with value
}
idBuffer.clear(); // Reset id buffer
valueBuffer.clear(); // Reset value buffer
vtoggle = !vtoggle; // Code to alternate whether or not we are converting to long or double
}
}
/**
* Read and return a certain number of bytes from our stream
*/
public byte[] readFromInput( InputStream is, int count ) throws IOException
{
byte[] buffer = new byte[ count ];
int bytesRead = 0;
int offset = 0;
while( ( bytesRead = is.read( buffer, offset, buffer.length - offset ) ) > 0 )
{
offset += bytesRead;
}
if( offset == buffer.length )
{
return buffer;
}
else
{
throw new IOException( "Unexpected end to stream." );
}
}
这显然只是一个模板,但希望它能指导您正确解决问题。
很难说出你真正想要实现的目标。
我的回答假设你需要这样的东西:
public Map<Integer, Double> read(InputStream stream);
尝试这样的事情:
public static void main(String[] args) throws IOException {
InputStream stream = ...;
byte[] buffer = new byte[12];
Map<Integer, Double> values = new HashMap<>();
while (stream.read(buffer) == 12) { // Could it read all data?
int id = readInt(buffer, 0);
double value = readDouble(buffer, 4);
values.put(id, value);
}
// use values
}
public static double readDouble(byte[] data, int offset) {
return Double.longBitsToDouble(readLong(data, offset));
}
public static long readLong(byte[] data, int offset) {
// Do some bit shifting to adjust the numbers.
return (((long) readInt(data, offset)) << 32) + readInt(data, offset + 4);
}
public static int readInt(byte[] data, int offset) {
return (data[offset + 0] << 24) + (data[offset + 1] << 16) + (data[offset + 2] << 8) + (data[offset + 3]);
}
请提供一些示例代码!
我猜你有一些ByteArrayInputStream
?看看 API:https://docs.oracle.com/javase/7/docs/api/java/io/ByteArrayInputStream.html
您可以简单地使用 read(...)
方法来实现您的目的:https://docs.oracle.com/javase/7/docs/api/java/io/ByteArrayInputStream.html#read(byte[],%20int,%20int)
这样,您可以执行以下操作:
ByteArrayInputStream in;
byte[] id = new byte[4];
in.read(id, 0, 4);
byte[] data = new byte[8];
in.read(data, 0, 8);
只需将其放入循环中即可完成。
如果 read(...)
方法返回 -1
,则流完成。如果 read(...)
方法返回的次数少于预期返回的次数,还可以检查错误。