【问题标题】:Get from ByteBuffer to byte[] does not write to byte[]从 ByteBuffer 获取到 byte[] 不写入到 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();
  }

【问题讨论】:

    标签: java bytearray bytebuffer


    【解决方案1】:

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

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

    【讨论】:

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

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

    【讨论】:

    • 错了。他的结果数组在循环内重新分配。
    • ByteArrayOutputStream 的好提示。这让事情变得更简单了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多