简体   繁体   中英

why the buffers have not been write into the FileChannel

I'm learning java NIO now, I have found an example to explain the gather operation for FileChannel as below:

public class ScattingAndGather {
    public static void main(String args[]) {
        gather();
    }

    public static void gather() {
        ByteBuffer header = ByteBuffer.allocate(10);
        ByteBuffer body = ByteBuffer.allocate(10);

        byte[] b1 = { '0', '1' };
        byte[] b2 = { '2', '3' };
        header.put(b1);
        body.put(b2);

        ByteBuffer[] buffs = { header, body };

        FileOutputStream os = null;
        FileChannel channel = null;
        try {
            os = new FileOutputStream("d:/scattingAndGather.txt");
            channel = os.getChannel();
            channel.write(buffs);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            if (channel != null) {
                try {
                    channel.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

while the result shows that, the file has been created, but it's empty, which is supposed to be 0123 in it, what's wrong for the example?

The problems occurs from the fact that you never reset the buffer's position.

When you create both your ByteBuffer objects they start at position zero. Whenever you add content into them, their position advances, meaning that when you attempt to write them out, they report as no more bytes to read. Thus before doing any kind of such operation you need to reset their position some how.

Buffer offers a few methods with the most easy to use being flip() . As you can see in the documentation here , it's usage is the following:

Flips this buffer. The limit is set to the current position and then the position is set to zero. If the mark is defined then it is discarded.

After a sequence of channel-read or put operations, invoke this method to prepare for a sequence of channel-write or relative get operations

Thus before writing them out you need to flip them. Also, since you're experimenting with java.nio I don't see why you should not use try with resources statements to manage your various resources. This way, you'll be avoiding the excessive boiler plate code of closing resources that can be auto-closed manually.

Using those your code can shrink significantly and be much more readable:

public static void gather() {
    ByteBuffer header = ByteBuffer.allocate(10);
    ByteBuffer body = ByteBuffer.allocate(10);

    byte[] b1 = { '0', '1' };
    byte[] b2 = { '2', '3' };
    header.put(b1);
    body.put(b2);

    //flip buffers before writing them out.
    header.flip();
    body.flip();
    ByteBuffer[] buffs = { header, body };

    try(FileOutputStream os = new  FileOutputStream("d:/scattingAndGather.txt");
 FileChannel channel = os.getChannel()) {
    channel.write(buffs);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM