Javaでは、OutputStream(自分でそのストリームにデータを入力する)のコンテンツをByteBufferに入れる必要があります。簡単な方法でそれを行う方法は?
7 に答える
を作成して書き込み、を使用しByteArrayOutputStream
て内容を抽出できます。次に、出力バイト配列の内容を使用してを作成します。byte[]
toByteArray()
ByteBuffer.wrap(byte [])
ByteBuffer
@DJClayworthの答えのより効率的な変形があります。
@sehが正しく認識したように、バッキングオブジェクトのコピーByteArrayOutputStream.toByteArray()
を返しますが、これは非効率的である可能性があります。ただし、バッキングオブジェクトとバイト数はどちらもクラスの保護されたメンバーです。したがって、ByteArrayOutputStreamの独自のバリアントを作成して、それらを直接公開できます。byte[]
byte[]
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については、このリンクを参照してください。
OutputStreamの代わりにPipedOutputStreamを使用してみてください。次に、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にアクセスし、extendクラスからカウントします
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;