Why does ByteBuffer's flip() method called "flip"? What is "flipped" here? According to apidoc, two successive flips won't restore original state, and multiple flips will probably tend limit() to become zero.
Can I "unflip" somehow to reuse bytes went out of a limit?
Can I concatenate tail to be flipped with some other data?
One fairly common use case for the ByteBuffer is to construct some data structure piece-by-piece and then write that whole structure to disk. flip is used to flip the ByteBuffer from "reading from I/O" (putting) to "writing to I/O" (getting): after a sequence of puts is used to fill the ByteBuffer, flip will set the limit of the buffer to the current position and reset the position to zero. This has the effect of making a future get or write from the buffer write all of what was put into the buffer and no more.
After finishing the put, you might want to reuse the ByteBuffer to construct another data structure. To "unflip" it, call clear. This resets the limit to the capacity (making all of the buffer usable), and the position to 0.
So, a typical usage scenario:
ByteBuffer b = new ByteBuffer(1024);
for(int i=0; i<N; i++) {
b.clear();
b.put(header[i]);
b.put(data[i]);
b.flip();
out.write(b);
}
Flip assigns the current position value to the limit property and sets the position property to 0. Flip is useful to drain only active elements from a buffer.
For example, below program prints "hello" instead of empty elements of the buffer. Method calls limit and position can be replaced with flip.
CharBuffer cbuff = CharBuffer.allocate(40);
cbuff.put("hello");
// These two lines below are what flip does
cbuff.limit(cbuff.position());
cbuff.position(0);
while(cbuff.hasRemaining()) {
System.out.println(cbuff.get());
}
See http://www.zoftino.com/java-nio-tutorial for more information on buffers and channels.
flip() method makes a buffer ready for a new sequence of channel-write or relative get operations: It sets the limit to the current position and then sets the position to zero.
Buffer keeps track of the data written into it. Post writing, flip() method is called to switch from writing to reading mode.
A buffer has a fixed capacity; it maintains 2 pointers: start and end. get() returns the byte at the start position and increments start. put() puts the byte at the end position and increments end. No flip()!
Related
I know that java NIO have two modes , the asynchronized and synchronized mode.When I am reading the javadoc of SocketChannel.read(), I get the explaination below:
Reads a sequence of bytes from this channel into the given buffer.
An attempt is made to read up to r bytes from the channel, where r is the number of bytes remaining in the buffer, that is, dst.remaining(), at the moment this method is invoked.
Suppose that a byte sequence of length n is read, where 0 <= n <= r. This byte sequence will be transferred into the buffer so that the first byte in the sequence is at index p and the last byte is at index p + n - 1, where p is the buffer's position at the moment this method is invoked. Upon return the buffer's position will be equal to p + n; its limit will not have changed.
A read operation might not fill the buffer, and in fact it might not read any bytes at all. Whether or not it does so depends upon the nature and state of the channel. **A socket channel in non-blocking mode, for example, cannot read any more bytes than are immediately available from the socket's input buffer; similarly, a file channel cannot read any more bytes than remain in the file. It is guaranteed, however, that if a channel is in blocking mode and there is at least one byte remaining in the buffer then this method will block until at least one byte is read.**
This method may be invoked at any time. If another thread has already initiated a read operation upon this channel, however, then an invocation of this method will block until the first operation is complete.
what make me confused is the explanation of asynchronized and sychronized read .Yes , in asynchronized mode, it will immediately read what is now already in buffer and return.But in synchronized mode,it is not the same?if there is something in buffer, why is does't not read it and return immediately?wait for what?
if there is something in buffer, why is does't not read it and return immediately?
I think you understood it wrong. As it is said in docs for int read(ByteBuffer dst)
The buffer into which bytes are to be transferred.
The channel reads bytes and writes them into buffer.
It is guaranteed, however, that if a channel is in blocking mode and
there is at least one byte remaining in the buffer then this method
will block until at least one byte is read.
at least one byte remaining in the buffer means that buffer still has free space. Functions boolean hasRemaining() and int remaining() are used for checking this.
wait for what?
Wait for reading some bytes from the channel or reaching the end-of-stream.
Reading on blocking channel couldn't return 0.
While studying the ByteBuffer class I got to thinking about an array wrapped ByteBuffer that might be constructed as follows:
byte data[] = new byte[10];
// Populate data array
ByteBuffer myBuffer = ByteBuffer.wrap(data);
int i = myBuffer.getInt();
Which, I thought, might retrieve the first 4 bytes of my byte array as an int value. However, as I studied further, I seemed to find that the ByteBuffer has two modes which are read and write and we can flip between them using the flip() method. However, since flip is basically a toggle, it pre-supposes than one knows the initial value to meaningfully flip between the read and write states.
What is the definition of the initial state of a ByteBuffer?
write?
read?
A function of how it was created (eg. allocate vs wrap)?
Strictly speaking the ByteBuffer itself doesn't track if it is "read" or "write"; that's merely a function of how it is used. A ByteBuffer can read and write at any time. The reason why we say flip switches the "mode" is because it is part of the common task of writing to the buffer, flipping it, then reading from the buffer.
Indeed, both allocate and wrap set the limit and capacity to be equal to the array size, and the position to zero. This means that read operations can read up to the whole array, and write operations can fill the whole array. You can therefore do either reading or writing with a newly allocated or wrapped ByteBuffer.
I am reading from an Inputstream with a bounded buffer of 200 bytes and I want to find a substring in it. I used the string.indexOf(substring).
But it does not return the right answer if substring crosses the boundary. e.g starts from 199th byte.
Any suggestions?
There are two approaches that I can think of:
Normalize the circular buffer (*) before executing indexOf(). By "normalize" I mean copy the bytes within the buffer so that the beginning of the buffer is at index 0, and therefore the contents of the buffer are not circular anymore. This will greatly improve the performance of searching through the buffer, but it will incur a performance penalty on the first search that follows a modification of the buffer, because at that moment you will have to first normalize. Since you are only dealing with a 200 byte buffer, the penalty will be negligible, and if you are planning to do multiple searches per buffer modification, the savings might end up being huge.
Write your own indexOf( MyCircularBuffer, String ) method which searches inside your circular buffer for the first character of the string and when found, performs the comparison of the remainder of the string by generating indexes based on the same logic that your circular buffer uses for generating indexes.
* We are writing software for computers with finite memory, so every single buffer is by definition a bounded buffer, so the term "bounded buffer" does not convey any useful information either with respect to how you are supposed to use it, or with respect to how it is internally structured. What you are referring to as "Bounded Buffer" is in fact a "Circular Buffer". The term "circular" still gives no hint about its use, but at least it gives a hint about its internal structure.
Typically, after a compact() to a ByteBuffer is called, I see that the new position will be set to the old limit such that the buffer is ready for a put().
But sometimes, I see that the position is 0 in a ByteBuffer (and limit = capacity) after a call to compact(). If so, would this happen only when position = capacity (or position = limit) before the call to compact?
The javadoc for ByteBuffer says "The buffer's position is then set to n+1 and its limit is set to its capacity.", but I seem to see the position set to 0 in my program.
It would happen if you've removed everything from the buffer, so it becomes the same as a clear(). That would imply that position = limit beforehand.
Why does ByteBuffer's flip() method called "flip"? What is "flipped" here? According to apidoc, two successive flips won't restore original state, and multiple flips will probably tend limit() to become zero.
Can I "unflip" somehow to reuse bytes went out of a limit?
Can I concatenate tail to be flipped with some other data?
One fairly common use case for the ByteBuffer is to construct some data structure piece-by-piece and then write that whole structure to disk. flip is used to flip the ByteBuffer from "reading from I/O" (putting) to "writing to I/O" (getting): after a sequence of puts is used to fill the ByteBuffer, flip will set the limit of the buffer to the current position and reset the position to zero. This has the effect of making a future get or write from the buffer write all of what was put into the buffer and no more.
After finishing the put, you might want to reuse the ByteBuffer to construct another data structure. To "unflip" it, call clear. This resets the limit to the capacity (making all of the buffer usable), and the position to 0.
So, a typical usage scenario:
ByteBuffer b = new ByteBuffer(1024);
for(int i=0; i<N; i++) {
b.clear();
b.put(header[i]);
b.put(data[i]);
b.flip();
out.write(b);
}
Flip assigns the current position value to the limit property and sets the position property to 0. Flip is useful to drain only active elements from a buffer.
For example, below program prints "hello" instead of empty elements of the buffer. Method calls limit and position can be replaced with flip.
CharBuffer cbuff = CharBuffer.allocate(40);
cbuff.put("hello");
// These two lines below are what flip does
cbuff.limit(cbuff.position());
cbuff.position(0);
while(cbuff.hasRemaining()) {
System.out.println(cbuff.get());
}
See http://www.zoftino.com/java-nio-tutorial for more information on buffers and channels.
flip() method makes a buffer ready for a new sequence of channel-write or relative get operations: It sets the limit to the current position and then sets the position to zero.
Buffer keeps track of the data written into it. Post writing, flip() method is called to switch from writing to reading mode.
A buffer has a fixed capacity; it maintains 2 pointers: start and end. get() returns the byte at the start position and increments start. put() puts the byte at the end position and increments end. No flip()!