【问题标题】:Best way to parse data stream containing of pairs of id and data point解析包含一对 id 和数据点的数据流的最佳方法
【发布时间】:2016-06-04 13:08:16
【问题描述】:

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

我的数据流遵循这种格式:

ID(4字节)DATA(8字节)ID(4字节)DATA(8字节)

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

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

我如何提取例如第一个 id(例如,000,整数)之后的第一个数据点(long),然后是第二个 id(001,整​​数)之后的第二个数据点(double)。

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

提前谢谢你和问候,

菲利普

【问题讨论】:

    标签: java parsing stream byte pipes-filters


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

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

      这显然只是一个模板,但希望它能指导您找到正确的解决方案。

      【讨论】:

      • 谢谢!这就是我想做的!完美。
      • @Ipsider 这是你最终使用的吗?如果是这样,我希望你能接受我的回答:)
      【解决方案3】:

      很难说出你真正想要达到的目标。

      我的回答假设您需要类似的东西:

      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]);
      }
      

      【讨论】:

      • 谢谢!这就是我想要的。我没有意识到如何根据 id “拆分”传入的流。完美!
      【解决方案4】:

      请提供一些示例代码!


      我猜你有一些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(...) 方法的返回值低于您的预期,您还可以检查错误。

      【讨论】:

      • 非常感谢您的评论。我会试试看。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-09-30
      • 1970-01-01
      • 2016-07-14
      • 1970-01-01
      • 1970-01-01
      • 2023-03-22
      • 1970-01-01
      相关资源
      最近更新 更多