1

I have a class works like FilterOutputStream.

public class WritableFilterChannel implements WritableChannel {

    public WritableFilterChannel(final WritableByteChannel channel) {
        super();
        this.channel = channel;
    }

    // isOpen(), close() delegates to the channel
    // write(ByteBuffer) overridden to work differently

    protected WritableByteChannel channel;
}

When I pass an instance of FileChannel, there is no way to force() other than close() it.

Is FileChannel#force is equivalent to OutputStream#flush? Do I always have to call it?

Do I have to do like this?

@Override
public void close() {
    if (channel instanceof FileChannel) throws IOException {
        ((FileChannel) channel).force(); // general solution?
    }
    channel.close();
}
Jin Kwon
  • 20,295
  • 14
  • 115
  • 184
  • 1
    If `channel.close();` doesn’t call `force()` internally, why should your `close()` method do it? – Holger Feb 01 '23 at 13:16
  • @Holger Just because any `FileChannel` would be wrapped in my class as an instance of `WritableFileChannel`? Thanks. – Jin Kwon Feb 02 '23 at 06:44
  • 2
    That doesn’t explain anything. If your `close()` method delegates to the wrapped channel’s `close()` method you already have exactly the same behavior, including all mandatory actions performed by that `close()` method. There are only two scenarios 1) calling `force()` is required. In that case you don’t need to call it, because `channel.close();` will already do it. 2) calling `force()` is not required. In that case you don’t need to call it, because it is not required. So, in either case, you don’t need to call it. That’s what makes the question so strange. By the way, the answer is 2). – Holger Feb 02 '23 at 09:33

1 Answers1

2

"Equivalent" is too strong a word. FileChannel.force(false) is similar to OutputStream.flush(). FileChannel's force() method offers stronger guarantees about the state of the file after it returns than OutputStream's flush() method.

Obviously you do not have to close() the FileChannel that you called the force() method on. You should only close the channel when you have finished with it. However, there is no guarantee that closing the channel will cause the equivalent of a force operation on it. If you need the behavior that force() specifies as part of the channel closure then you must explicitly call it the way you are doing in your close() method.

President James K. Polk
  • 40,516
  • 21
  • 95
  • 125
  • 1
    Calling `flush()` on a `FileOutputStream` has no effect at all. So calling this equivalent to `force` would be “too strong a word”, indeed. We could also say that these operations have nothing in common at all. – Holger Feb 01 '23 at 13:17
  • @Holger: It weird that someone follows you around upvoting your comments minutes after you make them. It's true that in current and past implementations `FileOutputStream.flush()` does nothing, but that is an implementation detail that could change (but not likely). – President James K. Polk Feb 01 '23 at 13:37
  • 1
    The contract of of `OutputStream.flush()` is that “*if any bytes previously written have been buffered … such bytes should immediately be written to their intended destination*” but `FileOutputStream` is not buffered. That’s why its `flush()` method doesn’t do anything. The Channel API is designed for unbuffered I/O in general, as the caller is supposed to control the buffers. So there is no `flush` method in the first place. `force` is closer to calling `getFD().sync()` on a `FileOutputStream`. Both operations only exists in the file specific specialization rather than the abstraction. – Holger Feb 01 '23 at 13:56
  • @Holger: How do you know `FileOutputStream` is not buffered? – President James K. Polk Feb 01 '23 at 13:59
  • 1
    Well, that’s the design since Java 1.0. If you want a buffered outputstream, you have to wrap the `FileOutputStream` in a `BufferedOutputStream`. Granted, `FileOutputStream`’s specification doesn’t say that it will not do buffering, on the other hand, its specification also doesn’t say that it won’t format your hard drive, so how do you know that `FileOutputStream` doesn’t format you hard drive? Usually by the fact that all classes that provide this feature name it explicitly, so all others do not have this feature. – Holger Feb 01 '23 at 14:11