Virtual Developer Workshop: Containerized Development with Docker
|Bruce Eckel's Thinking in Java||Contents | Prev | Next|
RandomAccessFile is used for files containing records of known size so that you can move from one record to another using seek( ), then read or change the records. The records don’t have to be the same size; you just have to be able to determine how big they are and where they are placed in the file.
At first it’s a little bit hard to believe that RandomAccessFile is not part of the InputStream or OutputStream hierarchy. It has no association with those hierarchies other than that it happens to implement the DataInput and DataOutput interfaces (which are also implemented by DataInputStream and DataOutputStream). It doesn’t even use any of the functionality of the existing InputStream or OutputStream classes – it’s a completely separate class, written from scratch, with all of its own (mostly native) methods. The reason for this may be that RandomAccessFile has essentially different behavior than the other IO types, since you can move forward and backward within a file. In any event, it stands alone, as a direct descendant of Object.
Essentially, a RandomAccessFile works like a DataInputStream pasted together with a DataOutputStream and the methods getFilePointer( ) to find out where you are in the file, seek( ) to move to a new point in the file, and length( ) to determine the maximum size of the file. In addition, the constructors require a second argument (identical to fopen( ) in C) indicating whether you are just randomly reading ( “r”) or reading and writing ( “rw”). There’s no support for write-only files, which could suggest that RandomAccessFile might have worked well if it were inherited from DataInputStream.
What’s even more frustrating is that you could easily imagine wanting to seek within other types of streams, such as a ByteArrayInputStream, but the seeking methods are available only in RandomAccessFile, which works for files only. BufferedInputStream does allow you to mark( ) a position (whose value is held in a single internal variable) and reset( ) to that position, but this is limited and not too useful.