117

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?

Suzan Cioc
  • 29,281
  • 63
  • 213
  • 385
  • 6
    It "flips" the buffer from read to write (and vice versa). http://thushw.blogspot.com/2009/10/java-bytebuffer-how-does-this-work.html – Brian Roach Feb 09 '13 at 23:53
  • 2
    @BrianRoach: It flips from read to write but is not as useful for write to read unless you are writing fixed-size structures. For flipping to write to read, use `reset` instead. – nneonneo Feb 10 '13 at 00:00
  • Remember to ask "objective" questions; or, at least, make the predominant question seem objective :D –  Feb 10 '13 at 00:12
  • @nneonneo - It was kinda non-question, wasn't really going to spend much time on explaining the details, hence just a comment and a link. – Brian Roach Feb 10 '13 at 03:33

4 Answers4

151

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);
}
nneonneo
  • 171,345
  • 36
  • 312
  • 383
  • A `WritableByteChannel`, such as `FileChannel` or `SocketChannel`. – nneonneo Feb 10 '13 at 00:16
  • 6
    Or anything else that has a `write(ByteBuffer)` method. (It is not really relevant what its type is ...) – Stephen C Feb 10 '13 at 01:35
  • 1
    It should `Buffer.clear` which reset limit to capacity and position to 0. `Buffer.reset` reset only position to `mark`. – Kelvin Ng Oct 15 '13 at 09:25
  • 1
    @KelvinNg: You're right; I've amended the answer to reflect this. Thanks for the nice catch! – nneonneo Oct 15 '13 at 18:10
  • In some scenarios (you have "unwritten" bytes left in the buffer, if for example the consumer can only consume 4 bytes at once) you may also want to use `compact()` which moves them to the beginning of the buffer so that you can continue reading bytes into the buffer after them. – mihi Apr 13 '15 at 21:04
  • @AdamHughes second loop iteration reuses the cleared buffer. Having the clear at the end of the loop is also possible (but still has one clear call too many) – eckes Oct 14 '16 at 14:08
  • @nneonneo: How does "reading" means (putting) and "writing" means (getting)? E.g. when we use `put` you write data into buffer. – user963241 Jun 18 '17 at 16:37
  • 1
    @user963241: read *from* I/O into buffer, write *from* buffer into I/O. – nneonneo Jun 18 '17 at 22:17
  • @KelvinNg Mark and reset are for `InputStreams`, not buffers. – user207421 Dec 01 '19 at 19:48
  • @user207421 OP fixed the bug in his code snippet at revision 2 https://stackoverflow.com/posts/14793037/revisions# – Kelvin Ng Dec 02 '19 at 11:38
15

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.

Arnav Rao
  • 6,692
  • 2
  • 34
  • 31
  • Thank you for the link to the very extensive coverage! It's so great when sources are included. The java API docs seemed to use the word 'flip' without explanation, as if it were a common computer science term, but obviously a few people (including me) haven't found that to be the case. – John Sep 03 '20 at 16:12
3

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.

vkohli
  • 65
  • 7
1

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

usr-local-ΕΨΗΕΛΩΝ
  • 26,101
  • 30
  • 154
  • 305
irreputable
  • 44,725
  • 9
  • 65
  • 93
  • 1
    [[citation needed]] (I haven't heard these complaints about `ByteBuffer`). Also, the docs say there's only a "current position", not a "start" and "end". – nneonneo Feb 10 '13 at 01:38
  • I have heard, you can take my word for it. – irreputable Feb 10 '13 at 01:41
  • 7
    So, what are the complaints? If you have some personal grievance that's OK too, but it does not do to just say "X API sucks, people said so". – nneonneo Feb 10 '13 at 01:42
  • 13
    Posting that link is literally all you had to do in the first place. I never accused you of lying, I merely asked you to elaborate on the source and the nature of the complaints. – nneonneo Feb 10 '13 at 01:50
  • 2
    this is just a place where people offer their help voluntarily, with the proper amount of effort they choose to. I do not need to expand each answer into a well researched academic paper. – irreputable Feb 10 '13 at 01:52
  • 9
    and this is also a place where people will not take someone's word unless it sounds credible. – arunmoezhi Jun 25 '13 at 01:02
  • 8
    You don't even need to give sources. It is blatantly obvious that ByteBuffer is ill designed. flip does not fill a purpose, it just introduces a source of bugs when you forget to flip. If they felt an uncontrollable urge to put it in, at least make flipped and unflipped ByteBuffers different classes, so the type system can catch the bugs. – Gurgeh Nov 05 '13 at 12:45
  • 2
    I respect people who offer criticism of standards despite the entrenchment of that standard. +1 +1 +1. – stu Jan 16 '14 at 21:29
  • 1
    `flip` sounds like the buffer direction is reversed. They need a verb to represent changing mode; `switch` is a keyword, so it's invalid, and `shift` has a whole other meaning in a bit-based context. `swap` or `change` are better choices than `flip`. – JoshDM Nov 01 '16 at 16:33
  • 4
    There is nothing here that answers the question. – user207421 May 24 '17 at 18:26
  • 3
    This does not answer the question at all. – Willwsharp Oct 23 '18 at 14:57