解析包含 id 和数据点对的数据流的最佳方式



我正在尝试编写一个简单的管道和过滤器系统,我目前正在一次解析一个字节的输入流。

我的数据流遵循以下格式:

ID (4 字节) 数据 (8 字节) ID (4 字节)

数据 (8 字节)

每个数据帧都有 6 对 ID 和数据。

解析此类流的最佳实践是什么?我希望能够过滤掉 id 和一些数据,这样我就会有一个只包含 DATA01、DATA02 等的表。

例如,

我如何提取第一个id(例如000,整数)之后的第一个数据点(long),然后在第二个id(001,整数)之后提取第二个数据点(双精度)。

我希望我能够详细说明我的问题。

提前感谢您和问候,

菲利普

试试preon。有关简单示例,请参阅此链接。

如果您不想使用库,那么 DataInputStream 非常适合您的用例。有关示例,请参阅此链接。

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." );
        }
    }

这显然只是一个模板,但希望它能指导您正确解决问题。

很难说出你真正想要实现的目标。

我的回答假设你需要这样的东西:

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(...) 方法返回的次数少于预期返回的次数,还可以检查错误。

相关内容

  • 没有找到相关文章

最新更新