簡體   English   中英

"如何將 OutputStream 中的數據放入 ByteBuffer?"

[英]How to put data from an OutputStream into a ByteBuffer?

在 Java 中,我需要將 OutputStream 中的內容(我自己將數據填充到該流中)放入 ByteBuffer。 如何以簡單的方式做到這一點?

"

您可以創建一個ByteArrayOutputStream並寫入它,然后使用toByteArray()將內容提取為byte[] 然后ByteBuffer.wrap(byte [])將使用輸出字節數組的內容創建一個ByteBuffer

@DJClayworth 的答案有一個更有效的變體。

正如@seh 正確注意到的那樣, ByteArrayOutputStream.toByteArray()返回支持byte[]對象的副本,這可能效率低下。 但是,支持的byte[]對象以及字節數都是ByteArrayOutputStream類的受保護成員。 因此,您可以創建自己的 ByteArrayOutputStream 變體來直接公開它們:

public class MyByteArrayOutputStream extends ByteArrayOutputStream {
  public MyByteArrayOutputStream() {
  }

  public MyByteArrayOutputStream(int size) {
    super(size);
  }

  public int getCount() {
    return count;
  }

  public byte[] getBuf() {
    return buf;
  }
}

使用這個類很容易:

MyByteArrayOutputStream out = new MyByteArrayOutputStream();
fillTheOutputStream(out);
return new ByteArrayInputStream(out.getBuf(), 0, out.getCount());

因此,一旦所有輸出都被寫入,同一個緩沖區將用作輸入流的基礎。

盡管上述答案解決了您的問題,但它們都沒有您對 NIO 的期望那樣高效。 ByteArrayOutputStream 或 MyByteArrayOutputStream 首先將數據寫入 Java 堆內存,然后將其復制到 ByteBuffer 中,這極大地影響了性能。

一個有效的實現是自己編寫 ByteBufferOutputStream 類。 其實這很容易做到。 你只需要提供一個 write() 方法。 有關ByteBufferInputStream ,請參閱此鏈接。

嘗試使用 PipedOutputStream 而不是 OutputStream。 然后,您可以連接 PipedInputStream 以從 PipedOutputStream 中讀取數據。

你說你自己在寫這個流? 如果是這樣,也許您可​​以實現自己的 ByteBufferOutputStream 並即插即用。

基類看起來像這樣:

public class ByteBufferOutputStream extends OutputStream {
    //protected WritableByteChannel wbc; //if you need to write directly to a channel
    protected static int bs = 2 * 1024 * 1024; //2MB buffer size, change as needed
    protected ByteBuffer bb = ByteBuffer.allocate(bs);

    public ByteBufferOutputStream(...) {
        //wbc = ... //again for writing to a channel
    }

    @Override
    public void write(int i) throws IOException {
        if (!bb.hasRemaining()) flush();
        byte b = (byte) i;
        bb.put(b);
    }

    @Override
    public void write(byte[] b, int off, int len) throws IOException {
        if (bb.remaining() < len) flush();
        bb.put(b, off, len);
    }

    /* do something with the buffer when it's full (perhaps write to channel?)
    @Override
    public void flush() throws IOException {
        bb.flip();
        wbc.write(bb);
        bb.clear();
    }

    @Override
    public void close() throws IOException {
        flush();
        wbc.close();
    }
    /*
}

// 從擴展類訪問受保護成員buf & count

class ByteArrayOutputStream2ByteBuffer extends ByteArrayOutputStream {
    public ByteBuffer toByteBuffer() {
        return ByteBuffer.wrap(buf, 0, count);
    }
}

請參閱具有動態重新分配的ByteBuffer支持的OutputStream的有效實現。

/**
 * Wraps a {@link ByteBuffer} so it can be used like an {@link OutputStream}. This is similar to a
 * {@link java.io.ByteArrayOutputStream}, just that this uses a {@code ByteBuffer} instead of a
 * {@code byte[]} as internal storage.
 */
public class ByteBufferOutputStream extends OutputStream {

    private ByteBuffer wrappedBuffer;
    private final boolean autoEnlarge;

https://gist.github.com/hoijui/7fe8a6d31b20ae7af945

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM