Random-Access Files
Tags: java, programming, learning, beginners
Published: 2024-07-01 13:50:18

Java provides the RandomAccessFile class to allow data to be read from and written to at any locations in the file. All of the streams you have used so far are known as _read-only_ or _write-only_ streams. These streams are called _sequential streams_. A file that is opened using a sequential stream is called a _sequential-access file_. The contents of a sequential-access file cannot be updated. However, it is often necessary to modify files. Java provides the **RandomAccessFile** class to allow data to be read from and written to at any locations in a file. A file that is opened using the **RandomAccessFile** class is known as a _random-access file_.

The **RandomAccessFile** class implements the **DataInput** and **DataOutput** interfaces, as shown in Figure below. The **DataInput** interface defines the methods for reading primitive-type values and strings (e.g., **readInt**, **readDouble**, **readChar**, **readBoolean**, **readUTF**) and the **DataOutput** interface defines the methods for writing primitive-type values and strings (e.g., **writeInt**, **writeDouble**, **writeChar**, **writeBoolean**, **writeUTF**).

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ku53yfo6485koyb5pvk0.png)

When creating a **RandomAccessFile**, you can specify one of two modes: **r** or **rw**. Mode **r** means that the stream is read-only, and mode **rw** indicates that the stream allows both read and write. For example, the following statement creates a new stream, **raf**, that allows the program to read from and write to the file **test.dat**:

`RandomAccessFile raf = new RandomAccessFile("test.dat", "rw");`

If **test.dat** already exists, **raf** is created to access it; if **test.dat** does not exist, a new file named **test.dat** is created, and **raf** is created to access the new file. The method **raf.length()** returns the number of bytes in **test.dat** at any given time. If you append new data into the file, **raf.length()** increases.

If the file is not intended to be modified, open it with the **r** mode. This prevents unintentional modification of the file.

A random-access file consists of a sequence of bytes. A special marker called a _file pointer_ is positioned at one of these bytes. A read or write operation takes place at the location of the file pointer. When a file is opened, the file pointer is set at the beginning of the file. When you read or write data to the file, the file pointer moves forward to the next data item. For example, if you read an **int** value using **readInt()**, the JVM reads **4** bytes from the file pointer, and now the file pointer is **4** bytes ahead of the previous location, as shown in Figure below.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hmarep8mjn6x8n2vz2be.png)

For a **RandomAccessFile raf**, you can use the **raf.seek(position)** method to move the file pointer to a specified position. **raf.seek(0)** moves it to the beginning of the file, and **raf.seek(raf.length())** moves it to the end of the file. The code below demonstrates **RandomAccessFile**.

```
package demo;
import java.io.*;

public class TestRandomAccessFile {

	public static void main(String[] args) throws IOException {
		try( // Create a random access file
			RandomAccessFile inout = new RandomAccessFile("inout.dat", "rw");
		) {
			// Clear the file to destroy the old contents if exists
			inout.setLength(0);
			
			// Write new integers to the file
			for(int i = 0; i < 200; i++)
				inout.writeInt(i);
			
			// Display the current length of the file
			System.out.println("Current file length is " + inout.length());
			
			// Retrieve the first number
			inout.seek(0); // Move the file pointer to the beginning
			System.out.println("The first number is " + inout.readInt());
			
			// Retrieve the second number
			inout.seek(1 * 4); // Move the file pointer to the second number
			System.out.println("The second number is " + inout.readInt());
			
			// Retrieve the tenth number
			inout.seek(9 * 4); // Move the file pointer to the tenth number
			System.out.println("The tenth number is " + inout.readInt());
			
			// Modify the eleventh number
			inout.writeInt(555);
			
			// Append a new number
			inout.seek(inout.length()); // Move the file pointer to the end
			inout.writeInt(999);
			
			// Display the new length
			System.out.println("The new length is " + inout.length());
			
			// Retrieve the new eleventh number
			inout.seek(10 * 4); // Move the file pointer to the eleventh number
			System.out.println("The eleventh number is " + inout.readInt());
		}
	}

}

```

`Current file length is 800
The first number is 0
The second number is 1
The tenth number is 9
The new length is 804
The eleventh number is 555 `

A **RandomAccessFile** is created for the file named **inout.dat** with mode **rw** to allow both read and write operations in line 8.

**inout.setLength(0)** sets the length to **0** in line 11. This, in effect, destroys the old contents of the file.

The **for** loop writes **200 int** values from **0** to **199** into the file in lines 14 and 15. Since each **int** value takes **4** bytes, the total length of the file returned from **inout.length()** is now **800** (line 18), as shown in the sample output.

Invoking **inout.seek(0)** in line 21 sets the file pointer to the beginning of the file. **inout.readInt()** reads the first value in line 22 and moves the file pointer to the next number. The second number is read in line 26.

**inout.seek(9 * 4)** (line 29) moves the file pointer to the tenth number. **inout.readInt()** reads the tenth number and moves the file pointer to the eleventh number in line 30. **inout.write(555)** writes a new eleventh number at the current position (line 33). The previous eleventh number is destroyed.

**inout.seek(inout.length())** moves the file pointer to the end of the file (line 36). **inout.writeInt(999)** writes a **999** to the file (line 37). Now the length of the file is increased by **4**, so **inout.length()** returns **804** (line 40).

**inout.seek(10 * 4)** moves the file pointer to the eleventh number in line 43. The new eleventh number, **555**, is displayed in line 44.