我正在尝试编写一个简单的管道和过滤器系统,我目前正在一次一个字节地解析输入流。
我的数据流遵循以下格式:
每个数据框都有6对id和数据。
解析此类流的最佳做法是什么?我希望能够过滤掉id和一些数据,这样我就可以得到一个只有DATA01,DATA02等的表。
如何在第一个id(000,例如整数)之后提取第一个数据点(long),然后在第二个id(001,整数)之后提取第二个数据点(double)。
我希望我能够详细阐述我的问题。
提前感谢您的问候,
菲利普
答案 0 :(得分:2)
答案 1 :(得分:1)
很难说出你真正希望实现的目标。
我的答案假设您需要以下内容:
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]);
}
答案 2 :(得分:1)
ByteBuffer是完成你想要做的事情的好课程。 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." );
}
}
这显然只是一个模板,但希望它能指导您找到解决问题的正确方法。
答案 3 :(得分:0)
请提供一些示例代码!
我猜你有一些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(...)
方法的返回值低于您预期的返回值,也可以检查错误。