32

I am aware that flip() set the current buffer position to 0 and set the limit to the previous buffer position whereas rewind() just set the current buffer position to 0.

In the following code, either I use rewind() or flip() i get the same result.

byte b = 127;
bb.put(b);
bb.rewind();//or flip();

System.out.println(bb.get());
bb.rewind();// or flip();
System.out.println(bb.get());

Could you provide me with a real example where the difference of these 2 methods really matters? Thanks in advance.

Line
  • 1,529
  • 3
  • 18
  • 42
Rollerball
  • 12,618
  • 23
  • 92
  • 161

6 Answers6

21

From the source code, they are very similar. You can see the follow:

public final Buffer flip() {
    limit = position;
    position = 0;
    mark = -1;
    return this;
}

public final Buffer rewind() {
    position = 0;
    mark = -1;
    return this;
}

So the difference is the flip set the limit to the position, while rewind not. Consider you have allocated a buffer with 8 bytes, you have filled the buffer with 4 bytes, then the position is set to 3, just show as follow:

    [ 1  1  1  1  0  0  0  0]
               |           |
flip           limit       |
rewind                     limit

So rewind just used limit has set appropriately.

lxy
  • 449
  • 4
  • 14
18

They're not equivalent at all.

A ByteBuffer is normally ready for read() (or for put()).

flip() makes it ready for write() (or for get()).

rewind() and compact() and clear() make it ready for read()/put() again after write() (or get()).

user207421
  • 305,947
  • 44
  • 307
  • 483
  • 1
    Can you please tell me why did you write `read()/put()` and `write()/get()`? Should not it be `read()/get()` and `write()/put()`? Since getting operation means reading and putting implies writing? – user963241 Jun 18 '17 at 21:49
  • @user963241 `read()` puts data into the buffer. `write()` takes it out. – user207421 May 01 '18 at 22:35
  • This is not a great answer because it explains the semantics of ByteBuffer operations in the context of using it with Channels/Sockets (or whatever has `read()` and `put()` methods that you speak about, we don't know) – haelix Dec 04 '18 at 13:54
  • @haekux No it doesn't. `ReadableChannel` has `read()`, `WriteableChannel` has `write()`, and `ByteBuffer` *itself* has `get()` and `put()`. There is no other way to get data in and out. This is rather basic. You personally may not know that, but that's not the answer's fault. – user207421 Dec 05 '18 at 00:28
  • @user207421 Yes it does. And it's confusing at first, because the OP's question had nothing to do with Channels, and my use-case has nothing to with Channels. But I understand that reading and writing from Channels into buffers is the most commonplace thing that people do with them. – haelix Dec 19 '18 at 17:48
  • @haelix What you are repeatedly claiming here is simply untrue. It's up there in black and white. The answer explains the operations in the context of `read()`and `write()` ***or*** `get()` and `put()`, to cover all the possibilities, as a god answer should, and the latter have nothing whatsoever to do with `Channels`. You are flying in the face of reality. – user207421 Mar 30 '19 at 22:53
  • 1
    @user207421 OK fine, I can obviously see what the answer contains. The point I was trying to make, unsuccessfully, was that the answer emphasizes `read` and `write` (of `Channel`), simply because read and write are mentioned first, and get and put are inside parantheses. It is just my opinion, that a great answer (which I said I believed yours is not) should emphasize methods of ByteBuffer itself. But the answer is still OK, it's just not _great_, and again, it's only an opinion, it hasn't got much to do with "reality". – haelix Apr 01 '19 at 23:28
  • @haekix Despite all this hair-splitting, the fact remains that the answer contains all the context you claimed it doesn't contain. – user207421 Mar 24 '21 at 09:26
4

The rewind( ) method is similar to flip( ) but does not affect the limit. It only sets the position back to 0. You can use rewind( ) to go back and reread the data in a buffer that has already been flipped. A common situation would be : after you use flip(), you read the data from the buffer, the you want to reread the data, this method would work.

sofia
  • 763
  • 8
  • 11
1

Here is an example where the two will produce different results. As you said, both set position to 0, the difference between the two is that flip sets the limit to the previous position.

So with flip, if you were writing ( put ) , the limit for reading ( get ) will become the position of the last element you wrote. If you try to read any more than that, it will throw an exception.

Rewind leaves the limit unchanged. Assuming it was at capacity ( buffer size ) , it will let you keep on reading beyond the data that you actually wrote, in this case reading the initial zeros that the buffer was initialized with.

ByteBuffer bb = ByteBuffer.allocateDirect(2);
byte b = 127;
bb.put(b);
bb.rewind();//or flip();

System.out.println(bb.get());  // will print 127 in either case
System.out.println(bb.get());  // will print 0 for rewind, BufferUnderflow exception for flip
Gonen I
  • 5,576
  • 1
  • 29
  • 60
1

Buffer has position, limit and capacity properties. You can allocate space for n number of elements while creating a buffer. Here n is the capacity. After buffer is allocated, position is set to 0 and limit is set to capacity.

If you filled the buffer with n-x number of elements, position will be set to n-x. Buffer will have empty elements after n-x.

If you want to drain the buffer at this point and that too want only non empty values, you need set limit to current position and position to zero. Using hasRemaining(), you can get elements till n-x. Flip sets the limit and position properties like described above.

Difference between flip and rewind is that flip sets the position to 0 and sets limit to active content. Method rewind just sets the position to 0.

For more information http://www.zoftino.com/java-nio-tutorial

Arnav Rao
  • 6,692
  • 2
  • 34
  • 31
0

@user963241 To add more colour on @EJP's answer.

flip() makes it ready for write() (or for get())

get() Example;

You might want to read data from the buffer (assuming that you had initially stored it in there)and use it for something else such as converting to a string and manipulate it for further use.

ByteBuffer buf = ByteBuffer.allocateDirect(80);
private String method(){
buf.flip();
byte[] bytes = byte[10]; //creates a byte array where you can place your data 
buf.get(bytes); //reads data from buffer and places it in the byte array created above
return bytes;
}

write() Example; After you have read data from socket channel into the buffer you might want to write it back to socket channel - assuming that you want to implement something like a server that echos same message received from client.

So you will read from channel to buffer and from buffer back to channel

SocketChannel socketChannel = SocketChannel.open();
...

ByteBuffer buf = ByteBuffer.allocateDirect(80);

int data = socketChannel.read(buf); // Reads from channel and places it into the buffer
while(data != -1){ //checks if not end of reading
buf.flip();        //prepares for writing
....
socketChannel.write(buf) // if you had initially placed data into buf and you want to read 
                         //from it so that you can write it back into the channel


  }
crakama
  • 759
  • 11
  • 25