【问题标题】:Java NIO: reading variable-sized blocksJava NIO:读取可变大小的块
【发布时间】:2009-08-22 20:08:39
【问题描述】:

我想从一个给定字节长度的 TCP 流中读取一个字符串,然后是实际数据。在 Python 中,我会这样做

length = ord(stream.read(1))
data = stream.read(length)

我如何在 Java NIO 中做同样的事情?我有一个缓冲区(容量为 257)

stream.read(buffer); // cannot specify a size here
int length = buffer.get();
byte[] data = new byte[length];
buffer.get(data);

不幸的是,这不起作用:get() 调用读取 过去 缓冲区中的数据 :-(

我可能需要一些翻转、倒带、重置等的组合,但我想不通。

【问题讨论】:

  • 在您的 Java 示例中,stream 是什么类型的对象?

标签: java buffer nio


【解决方案1】:

如果streamSocketChannelbufferByteBuffer,您可以执行以下操作:

//assuming buffer is a ByteBuffer
buffer.position(0);
buffer.limit(1);
while (buffer.hasRemaining()) { 
   stream.read(buffer);
}
buffer.rewind();

//get the byte and cast it into the range 0-255
int length = buffer.get() & 0xFF;
buffer.clear();
buffer.limit(length);
while (buffer.hasRemaining()) { 
   stream.read(buffer);
}
buffer.rewind();
//the buffer is now ready for reading the data from

【讨论】:

  • 谢谢,这应该可以正常工作 - 尽管它看起来相当复杂。
  • 它没那么简单,必须记住它没有必要一次接收所有字节,或者可能一次接收到多条消息。
【解决方案2】:

我建议,你看看 java.nio.channel.GatheringByteChannel 和 DatagramChannel。您需要根据需要指定数据报。

这就是您在 Python 示例中所做的(第一个字节表示有效负载长度,使用此长度读取播放负载),这看起来很容易出错(!)。

数据报是数据流的规范。它在逻辑上将您的流划分为包。因此,更好的策略是首先发送一个有效负载包,它指示有效负载的长度(和包大小)。编辑:当然,流的双方必须使用相同的协议/数据报语言。

【讨论】:

  • 我无法理解您的建议。 GatheringByteChannel 是一个已经由我已经在使用的 SocketChannel 实现的接口 - AFAIU,这是用于 TCP 的标准通道。 DatagramChannel 是无关紧要的,因为那是 UDP,我正在做 TCP。我也不明白为什么有一个协议首先发送长度然后有效负载容易出错 - 例如,HTTP 1.1 就是这样工作的。
  • 我错过了您的问题的一些细节。想一想,与 ByteBuffer 的方法相比,分配问题更多;)无论如何,如果您的有效负载不超过 255 字节,Bkkbrad 的解决方案是直截了当的。
猜你喜欢
  • 1970-01-01
  • 2022-08-19
  • 1970-01-01
  • 1970-01-01
  • 2013-10-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多