7 Replies Latest reply: Apr 11, 2013 10:50 AM by 963772 RSS

    Java NIO - Invoking compact() method on buffer object

    963772
      Hello,

      I have a question about invoking the compact() method on a buffer object. For instance consider the following piece of code:


      import java.io.*;
      import java.nio.*;
      import java.nio.channels.*;

           public class FileCopy3 {
      public static void main(String[] args) throws IOException {
      ReadableByteChannel in = new FileInputStream(args[0]).getChannel();
      WritableByteChannel out;
      if (args.length > 1) out = new FileOutputStream(args[1]).getChannel();
      else out = Channels.newChannel(System.out);

      copy(in, out);

      }

      public static void copy(ReadableByteChannel in, WritableByteChannel out)
      throws IOException
           {

      ByteBuffer buffer = ByteBuffer.allocateDirect(32 * 1024);
           while(in.read(buffer) != -1 || buffer.position() > 0) {
      buffer.flip();
      out.write(buffer);
      buffer.compact();
      }
      }
      }

      why should we concerning about compacting the buffer after writing it's contents thoroughly ?! Is it not true that the write() method above, should drain the whole buffer contents and write its contents to the output channel? Then why should we concern about the remaining data ? Is it not fully drained ? Where does this remaining data came from ?


      Thanks,

      Edited by: 960769 on Apr 10, 2013 2:32 AM
        • 1. Re: Java NIO - Invoking compact() method on buffer object
          EJP
          why should we concerning about compacting the buffer after writing its contents thoroughly?
          (1) That code isn't guaranteed to 'write the contents thoroughly'.
          (2) To remove what has been written from the buffer so it won't be written again.
          (3) To reconfigure the buffer so it is ready for another read, i.e. undo the effects of flip().
          Is it not true that the write() method above, should drain the whole buffer contents
          No.
          and write its contents to the output channel?
          As much as it can, yes.
          Then why should we concern about the remaining data?
          Because it hasn't been written yet.
          Is it not fully drained?
          Not necessarily. That's why write() returns a count.
          Where does this remaining data came from?
          From the read().
          • 2. Re: Java NIO - Invoking compact() method on buffer object
            963772
            Thank you for your reply,

            I'm a bit confused ... If the buffer demarcate the available data by means of position and limit markers ( as it's done by calling flip ) and the write method returns the number of number of bytes which are read, then why it is not guaranteed that the write() method drains the buffer contents thoroughly ?

            Sam,
            • 3. Re: Java NIO - Invoking compact() method on buffer object
              EJP
              The question is fallacious. The 'why' part doesn't follow logically from the 'if' part.

              There is no wording in the specification of the write() method that suggests it is required to transfer everything, and, again, that's why it returns a count. Compare OutputStream.write(), which is required to transfer everything, and doesn't return a count.
              • 4. Re: Java NIO - Invoking compact() method on buffer object
                963772
                Then i must ask why the write method is not guaranteed to drain the whole buffer ?! Technical articles often address this situation as the effect of partial read or write. When does this partial read/write happen? Why sometimes some bytes remain in the buffer after the read and write operations ?

                Edited by: 960769 on Apr 11, 2013 4:28 PM

                Edited by: 960769 on Apr 11, 2013 4:33 PM
                • 5. Re: Java NIO - Invoking compact() method on buffer object
                  EJP
                  Because the medium being written to may not permit it. For example, a socket in non-blocking mode. If all the data won't fit into the socket send buffer in the kernel, the write() method has no other sensible option but to transfer what does fit and return that count, and rely in the application retrying later with the remaining data.
                  • 6. Re: Java NIO - Invoking compact() method on buffer object
                    gimbal2
                    Point being: you can't ask for implementation details when you're talking about an API. There are no implementation details, it might be anything. You'd first have to define a specific context (local filesystem, over a network, beaming through space from satelite to satelite, etc.) and perhaps then you could go into specifics but even then - you shouldn't really care about the WHY of a specific case, you can't make any assumptions about it being the way it is or STAYING the way it is so you just need deal with the solution that is always safe regardless of context, environment and implementation. Which is usually the most work, but that's life.
                    • 7. Re: Java NIO - Invoking compact() method on buffer object
                      963772
                      Thank you EJP, this is very helpful.