-
Notifications
You must be signed in to change notification settings - Fork 2
Recipes
Table of Contents
- How can I read/write non-primitive values?
- How can I read/write bits from/to
(In|Out)putStream
s? - How can I read/write bits from/to
byte[]
s? - How can I read/write
byte[]
values? -
How can I read/write bits from/to
(Readable|Writable)ByteChannel
s?
You can use your own Bit(Reader|Writer)<T>
.
class User {
@NotNull String name;
@Max(127) @PositiveOrZero int age;
}
class UserProcessor implements BitReader<User>, BitWriter<User> {
@Override
public User read(BitInput input) throws IOException { // BitReader<User>
var value = new User();
value.name = nameReader.read(input);
value.age = input.readInt(true, 7); // 0 - 127
return value;
}
@Override
public void write(BitOutput output, User value) throws IOException { // BitWriter<User>
nameWriter.write(output, value.name);
output.writeInt(true, 7, value.age);
}
BitReader<String> nameReader = StringReader.compressedUtf8();
BitWriter<String> nameWriter = StringWriter.compressedUtf8();
}
Now you can write/read using the processor.
BitOutput output = ;
output.writeObject(new UserProcessor(), new User("Jane", 19));
BitInput input = ;
var user = input.readObject(new UserProcessor());
assert "Jane".equals(user.name);
assert user.name = 19;
Here come how to read bits from a File
.
try(InputStream stream = new FileInputStream("file")) {
BitInput input = BitInputFactory.from(stream);
// read bits here
input.align(1);
}
Here comes how to write bits to a (connected) Socket
.
try(Socket socket = connect()) {
BitOutput output = BitOutputFactory.from(socket.getOutputStream());
// write bits here!
output.align(1);
}
You can use the ByteArrayInputStream and/or the ByteArrayOutputStream.
There are a reader and a writer for reading/writing byte[]
values.
BitWriter<byte[]> writer = new ByteArrayWriter(Byte.SIZE);
BitOutput output = ;
output.writeObject(writer, new byte[0]);
BitReader<byte[]> reader = new ByteArrayReader(Byte.SIZE);
BitInput input = ;
byte[] value = input.readObject(reader);
You can use ChannelByte(Input|Output)
for reading/writing bits from (Readable|Writable)ByteChannel
s.
In case you have noticed that the those classes use a ByteBuffer
whose capacity is 1
, you can make your own Byte(Reader|Writer)
which uses a bigger ByteBuffer
.
Let's start with a channel to write.
try (var channel = openChannelToWrite()) {
}
Now you want to use a buffer whose capacity is greater than 1
.
try (var channel = openChannelToWrite()) {
final var buffer = ByteBuffer.allocate(2); // right?
}
Now you can use the BufferByteOutput
whose write(int)
method is overridden to write the buffer's content to the channel
when it gets full.
try (var channel = openChannelToWrite()) {
final var buffer = ByteBuffer.allocate(2);
final var byteOutput = new BufferByteOutput(buffer) {
@Override
public void write(final int value) throws IOException {
if (!buffer.hasRemaining()) { // the buffer is full
for (buffer.flip(); buffer.position() == 0; ) { // single space is enough
channel.write(buffer);
}
buffer.compact();
}
super.write(value); // put next octet to the buffer
}
};
}
Now you can write bits to a BitOutput
which writes bytes to the byteOutput
we just created.
final var bitOutput = new ByteOutputAdapter(byteOutput);
// write some bits here!
final var padded = bitOutput.align(1); // pads zero bits to align 8-bits
And here comes the most import part of draining all remaining bytes in the buffer
to the channel
.
for (buffer.flip(); buffer.hasRemaining(); ) {
channel.write(buffer);
}
Using bigger buffer for reading bits has same manner with that of writing.
try (var channel = openChannelToRead()) {
final var buffer = ByteBuffer.allocate(2);
buffer.position(buffer.capacity()); // important! the buffer needs to be filled first!
final var byteInput = new BufferByteInput(buffer) {
@Override
public int read() throws IOException {
if (!buffer.hasRemaining()) {
for (buffer.clear(); buffer.position() == 0; ) { // single byte should be enough
if (channel.read(buffer) == -1) {
throw new EOFException("reached to an end");
}
}
buffer.flip();
}
return super.read(); // get next octet from the buffer
}
};
final var bitInput = new ByteInputAdapter(byteInput);
// read some bits here
final var discarded = bitInput.align(1);
}