position set to 0 after compact() of ByteBuffer - java

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.

Related

Java ByteBuffer, is flip necessary or usefull? [duplicate]

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()!

glDrawBuffers should have flipped IntBuffer?

I have the following code:
IntBuffer DrawBuffers = Utils.createIntBuffer(2);
int bfs[] = {GL30.GL_COLOR_ATTACHMENT0, GL30.GL_COLOR_ATTACHMENT1};
for(int i = 0; i < 2; i++)
DrawBuffers.put(bfs[i]);
DrawBuffers.flip();
GL20.glDrawBuffers(DrawBuffers);
If I flip the IntBuffer then the int Status = GL30.glCheckFramebufferStatus(GL30.GL_FRAMEBUFFER); don't equal GL_FRAMEBUFFER_COMPLETE, if I don't flip it then I get the Status right, but I get a black texture instead of the desired texture, I looked throught my code over and over for 2 days now, my best bet is that this part of the code is somehow wrong, the rest seems ok.
Should the IntBuffer be flipped before using it in glDrawBuffers(IntBuffer) ?
Yes, all buffers should be flipped before being passed to LWJGL.
The underlying GL API expects an array for functions that take a Java buffer. The size of that array is a parameter in GL's C language bindings, but hidden from you in Java because LWJGL calculates it as the difference between the current position and the end position.
Unless you flip a java.nio.Buffer, which sets the "current" position to the beginning of a buffer, the current position is going to be the end position after calling put (...). Thus, LWJGL passes an array of size 0 to the C-based OpenGL API it sits on top of. If you call glDrawBuffers (...) with size 0, it sets everything to GL_NONE, which is definitely going to produce the behavior your described.

stringBuffer insert method using capacity as a parameter

public class example{
public static void main(String args[]) {
StringBuffer s1 = new StringBuffer(10);
s1.insert(0,avaffffffffffffffffffffffffffffffffffffffffffvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv");
System.out.println(s1);
}
}
the output of this code is coming as avaffffffffffffffffffffffffffffffffffffffffffvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv.
what is the use of parameter 10 in the StringBuffer class's method?
if 10 is the size of Buffer and 0 is the offset of insert method then how will we get the whole string as an output?
From JavaDoc:
A string buffer is like a String, but can be modified. At any
point in time it contains some particular sequence of characters, but
the length and content of the sequence can be changed through certain
method calls
10 is just initial capacity (continue reading JavaDoc):
Every string buffer has a capacity. As long as the length of the character sequence contained in the string buffer does not exceed the capacity, it is not necessary to allocate a new internal buffer array. If the internal buffer overflows, it is automatically made larger.
Read the docs:
capacity - the initial capacity.
So it is not the 'size'.
what is the use of parameter 10 in the StringBuffer class's method? if 10 is the size of Buffer and 0 is the offset of insert method then how will we get the whole string as an output?
The answer is that you can make the initial capacity smaller if you know that it is not likely to be used up. When a string buffer is created, memory has to be allocated. The default size is 16, but if you only want to use it for one character, you can specify that is initial capacity is 1, and since it will only resize when you add more than one character to it, you can avoid wasting memory.
The same applies to the parameters in things like HashSet(n). It will resize if you add elements too it, but if you know exactly how many elements it is going to have you can save a little memory and the operations needed for resizing by specifying its size exactly.

What is the purpose of ByteBuffer's flip method? (And why is it called "flip"?)

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()!

how to find out how many bytes I've written to bytebuffer (new to java)

I've tried reading the documentation, but there is no explanation of what is limit, mark etc. Annyoing thing is that the ByteBuffer.limit function's description says that it returns limit. now what is limit? Is it same or different from capacity...
End of the day, I want to know how many bytes I've 'put' into the buffer
If i allocate buffer with size 1024 and write the word "hello" into it. How can I get the result of 5 bytes written to the buffer?
Thanks
What you want to know is explained in the java.io.Buffer documentation.
A buffer's capacity is the number of elements it contains. The
capacity of a buffer is never negative and never changes.
A buffer's limit is the index of the first element that should not
be read or written. A buffer's limit is never negative and is never
greater than its capacity.
A buffer's position is the index of the next element to be read or
written. A buffer's position is never negative and is never greater
than its limit.
Invariants
The following invariant holds for the mark, position, limit, and
capacity values:
0 <= mark <= position <= limit <= capacity
A newly-created buffer always has a position of zero and a mark that
is undefined. The initial limit may be zero, or it may be some other
value that depends upon the type of the buffer and the manner in which
it is constructed. Each element of a newly-allocated buffer is
initialized to zero.
Marking and resetting
A buffer's mark is the index to which its position will be reset when
the reset method is invoked. The mark is not always defined, but when
it is defined it is never negative and is never greater than the
position. If the mark is defined then it is discarded when the
position or the limit is adjusted to a value smaller than the mark. If
the mark is not defined then invoking the reset method causes an
InvalidMarkException to be thrown.
The write() method returns the numbered bytes transferred. You're overcomplicating this.

Categories