26

Like the title; Does closing a FileChannel close the underlying file stream?


From the AbstractInterruptibleChannel.close() API docs you can read:

Closes this channel.

If the channel has already been closed then this method returns immediately. Otherwise it marks the channel as closed and then invokes the implCloseChannel method in order to complete the close operation.

Which invokes AbstractInterruptibleChannel.implCloseChannel:

Closes this channel.

This method is invoked by the close method in order to perform the actual work of closing the channel. This method is only invoked if the channel has not yet been closed, and it is never invoked more than once.

An implementation of this method must arrange for any other thread that is blocked in an I/O operation upon this channel to return immediately, either by throwing an exception or by returning normally.

And that doesn't say anything about the stream. So in fact, when I do:

public static void copyFile(File from, File to) 
        throws IOException, FileNotFoundException {

    FileChannel sc = null;
    FileChannel dc = null;

    try {
        to.createNewFile();

        sc = new FileInputStream(from).getChannel(); 
        dc = new FileOutputStream(to).getChannel();

        long pos = 0;
        long total = sc.size();
        while (pos < total)
            pos += dc.transferFrom(sc, pos, total - pos);

    } finally {
        if (sc != null) 
            sc.close();
        if (dc != null) 
            dc.close();
    }
}

...I leave the streams open?

dacwe
  • 43,066
  • 12
  • 116
  • 140

1 Answers1

22

The answer is 'yes' but there's nothing in the Javadoc that actually says so. The reason is that FileChannel itself is an abstract class, and its concrete implementation provides the implCloseChannel() method, which closes the underlying FD. However due to that architecture and the fact that implCloseChannel() is protected, this doesn't get documented.

Kara
  • 6,115
  • 16
  • 50
  • 57
user207421
  • 305,947
  • 44
  • 307
  • 483
  • Yes, seems correct, looking at sources of [`FileChannelImpl` (openkdk-7)](http://www.docjar.com/html/api/sun/nio/ch/FileChannelImpl.java.html) `implCloseChannel` closes the underlying stream. – dacwe Oct 19 '12 at 10:22
  • What is the "underlying FD"? Did you mean FC for FileChannel? – splash Sep 03 '13 at 08:52
  • @splash FD means 'file descriptor', the small integer that the operating system gives you when you call `open().` The second part of your question doesn't make sense. This already *is* a `FileChannel:` there is no 'underlying' `FileChannel.` – user207421 Dec 11 '13 at 22:44
  • 1
    But what happens if you let go of the reference to the stream... and then it gets `finalize()`d? From a quick glance a the code it looks like it will close the associated `FileDescriptor`. So this means if you just care about using the channel and drop the stream it was created from, planning to close the channel later instead, your channel could get closed out from under you unexpectedly. – Archie Aug 21 '15 at 20:04
  • 2
    @Archie `FileChannelImpl` has a `parent` object which is set to either the `FileInputStream` or `FileOutputStream` that created it, specifically ' to prevent finalization of creating stream '. The circumstance you describe cannot arise. – user207421 May 11 '16 at 10:27