File Descriptors

As I've said several times so far, the existence of a java.io.File object doesn't imply the existence of the file it represents. A java.io.FileDescriptor object does, however, refer to an actual file:

public final class FileDescriptor extends Object

A FileDescriptor object is an abstraction of an underlying machine-specific structure that represents an open file. While file descriptors are very important for the underlying OS and filesystem, their only real use in Java is to guarantee that data that's been written to a stream is in fact committed to disk, that is, to synchronize between the program and the hardware.

In addition to open files, file descriptors can also represent open sockets. There are also three file descriptors for the console: System.in, System.out, and System.err. These are available as the three mnemonic constants FileDescriptor.in, FileDescriptor.out, and FileDescriptor.err:

public static final FileDescriptor in
public static final FileDescriptor out
public static final FileDescriptor err

Because file descriptors are very closely tied to the native operating system, you never construct your own file descriptors. Various methods in other classes that refer to open files or sockets may return them. Both the FileInputStream and FileOutputStream classes and the RandomAccessFile class have a getFD( ) method that returns the file descriptor associated with the open stream or file:

public final FileDescriptor getFD( ) throws IOException

Since file descriptors are only associated with open files and sockets, they become invalid as soon as the file or socket is closed. You can test whether a file descriptor is still valid with the valid( ) method:

public native boolean valid( )

This returns TRue if the descriptor is still valid or false if it isn't.

The one real use to which a client programmer can put a file descriptor object is to sync a file. This is accomplished with the aptly named sync( ) method:

public native void sync( ) throws SyncFailedException

The sync( ) method forces the system buffers to write all the data they contain to the actual hardware. Generally, you'll want to flush the stream before syncing it. Flushing clears out Java's internal buffers. Syncing clears out the operating system's, device driver's, and hardware's buffers. If synchronization does not succeed, sync( ) throws a java.io.SyncFailedException, a subclass of IOException.