从 ByteBuffer 获取到 byte[] 不写入到 byte[]

Posted

技术标签:

【中文标题】从 ByteBuffer 获取到 byte[] 不写入到 byte[]【英文标题】:Get from ByteBuffer to byte[] does not write to byte[] 【发布时间】:2012-03-22 09:53:38 【问题描述】:

我从 SocketChannel 连续读取 BLOCKSIZE(例如 512)字节块到 ByteBuffer 中。然后,我想将 ByteBuffer 内容附加到 byte[] 并进行下一轮。结果将是一个 byte[],其中包含从 SocketChannel 读取的所有字节。

现在,System.arraycopy(...) 按预期工作。但是当我使用 ByteBuffer 的 get(result, offset, length) 时,什么都没有写入。结果数组值保持为零。

为什么会这样?

  public final static int BLOCKSIZE = 512;

  public byte[] getReceivedData() 
    int offset = 0, read;
    byte[] result = ;
    ByteBuffer buffer = ByteBuffer.allocate(BLOCKSIZE);
    try 
      while (true) 
        read = _socketChannel.read(buffer);
        if (read < 1) 
          // Nothing was read.
          break;
        

        // Enlarge result so we can append the bytes we just read.
        result = Arrays.copyOf(result, result.length + read);

        // This works as expected.
        System.arraycopy(buffer.array(), 0, result, offset * BLOCKSIZE, read);

        // With this, however, nothing is written to result. Why?
        buffer.get(result, offset * BLOCKSIZE, read);

        if (read < BLOCKSIZE) 
          // Nothing left to read from _socketChannel.
          break;
        

        buffer.clear();
      
     catch (IOException e) 
      e.printStackTrace();
    
    return result;
  

编辑:

我注意到offset++ 也不见了。因此,如果通道上的字节数超过BLOCKSIZE,事情就会变得一团糟......

无论如何,ByteArrayOutputStream 确实让事情变得更简单,所以我决定使用它。

工作代码:

  public byte[] getReceivedData() 
    int read;
    ByteArrayOutputStream result = new ByteArrayOutputStream();
    ByteBuffer buffer = ByteBuffer.allocate(BLOCKSIZE);
    try 
      while (true) 
        buffer.clear();
        read = _socketChannel.read(buffer);
        if (read < 1) 
          break;
        
        result.write(buffer.array(), 0, read);
        if (read < BLOCKSIZE) 
          break;
        
      
     catch (IOException e) 
      e.printStackTrace();
    
    return result.toByteArray();
  

【问题讨论】:

【参考方案1】:

你需要flip()get()之前的缓冲区,然后compact()它。

如果read == -1,你不仅需要跳出循环,还要关闭通道。

【讨论】:

flip() 成功了,谢谢。我认为compact() 不是必需的。在 get()ing 缓冲区中的所有内容之后,没有任何东西可以压缩,而且每次迭代都是 clear()ed。另外,感谢您关闭频道的提示。我知道渠道保持开放,这是有意的。客户可以随时发送新数据。 @riha 错了。在您获得 -1 后,没有客户会再向您发送任何数据。那是通道上的流结束,这意味着对等方已关闭连接,或者至少将其关闭以进行输出。关闭它。 嗯好吧,那它也确实应该在我这边关闭。虽然这在我的情况下永远不应该发生,但那是另一回事了。再次感谢。【参考方案2】:

您的结果数组的长度为 0,不能保存任何信息。字节数组不会增长,并且您无法附加缓冲区的内容。使用 java.io.ByteArrayOutputStream 累加结果。

【讨论】:

错了。他的结果数组在循环内重新分配。 ByteArrayOutputStream 的好提示。这让事情变得更简单了。

以上是关于从 ByteBuffer 获取到 byte[] 不写入到 byte[]的主要内容,如果未能解决你的问题,请参考以下文章

如何从 ByteBuffer 中获取已使用的 byte[]

从 ByteBuffer 读取字符串而不使用双缓冲

如何将 byte[] 转换为 bytebuffer 本机内存?

Java:从 ByteBuffer 扩展

用 ByteBuffer 处理 byte[]

ByteBuffer 到字节数组