-
-
Save tanghaodong25/366e0e18687262ddb59dfc3dd21d30d7 to your computer and use it in GitHub Desktop.
OutputStream that writes to a direct ByteBuffer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package io.github.ncruces.utils; | |
import java.io.OutputStream; | |
import java.nio.ByteBuffer; | |
public final class ByteBufferOutputStream extends OutputStream { | |
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; | |
private ByteBuffer buf; | |
public ByteBufferOutputStream() { buf = ByteBuffer.allocate(32); } | |
public ByteBufferOutputStream(int size) { | |
if (size < 0) throw new IllegalArgumentException("size < 0"); | |
buf = ByteBuffer.allocateDirect(size); | |
} | |
public synchronized int size() { return buf.position(); } | |
public synchronized void reset() { buf.clear(); } | |
public synchronized ByteBuffer toByteBuffer() { | |
ByteBuffer result; | |
if (buf.isDirect()) { | |
result = buf.asReadOnlyBuffer(); | |
} else { | |
result = ByteBuffer.allocateDirect(buf.flip().limit()).put(buf); | |
buf.limit(buf.capacity()); | |
} | |
result.flip(); | |
return result; | |
} | |
@Override | |
public synchronized void write(int b) { | |
if (buf.remaining() == 0) expand(1); | |
buf.put((byte)b); | |
} | |
@Override | |
public synchronized void write(byte[] b) { | |
if (b.length == 0) return; | |
if (b.length > buf.remaining()) expand(b.length); | |
buf.put(b); | |
} | |
@Override | |
public synchronized void write(byte[] b, int off, int len) { | |
if ((off | len | off + len | b.length - (off + len)) < 0) { | |
throw new IndexOutOfBoundsException(); | |
} | |
if (len == 0) return; | |
if (len > buf.remaining()) expand(len); | |
buf.put(b, off, len); | |
} | |
@Override | |
public void close() {} | |
private void expand(int len) { | |
ByteBuffer old = buf; | |
int oldCapacity = old.capacity(); | |
int minCapacity = old.position() + len; | |
int newCapacity = oldCapacity + (oldCapacity >> 1); | |
if (newCapacity - minCapacity < 0) | |
newCapacity = minCapacity; | |
if (newCapacity - MAX_ARRAY_SIZE > 0) { | |
if (minCapacity < 0) throw new OutOfMemoryError(); | |
newCapacity = minCapacity > MAX_ARRAY_SIZE ? minCapacity : MAX_ARRAY_SIZE; | |
} | |
buf = ByteBuffer.allocate(newCapacity); | |
old.flip(); | |
buf.put(old); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment