ZOFTINO.COM android and web dev tutorials

Java Random Access Files

Java IO and NIO APIs allow you to randomly access files to read content from and write content to files anywhere in the files. With sequential access, content is read and written from the beginning of the file. Java IO character streams and byte streams access files sequentially.

Java IO provides RandomAccessFile class which allows you to access files randomly. Java new IO (NIO) API provides SeekableByteChannel interface and FileChannel class for accessing files randomly. In this tutorial, you can learn how to access files radomly using both RandomAccessFile and SeekableByteChannel and FileChannel with examples.

Table of Contents

RandomAccessFile

RandomAccessFile class can be used for both reading and writing random access files. RandomAccessFile instance can be created by passing either file name or File object and mode to its constructor. Mode specifies whether the file needs to be opened for read, write or both operations.

RandomAccessFile raf =  new RandomAccessFile(file, "rw");

The possible values for mode are r (opens for reading, an exception will be thrown if you try to write), rw (opens for both reading and writing, it will create a file if file doesn’t exist), rws ( allows read and write, asynchronously updates metadata and content changes to storage) and rwd (opens for read and write, asynchronously updates only content to ensure that content is not lost).

RandomAccessFile provides methods to read and write to files. To read byte by byte, you can read() method and to read file content into bytes array, you need to pass byte array to read() method. Similarly, you can use write method write single byte or byte array to a file.

To read content of primitive types, you can use read method for each primitive type such as reading, readShort, readLong, readFloat, readDouble, readBoolean, etc. Similarly write methods exist for writing primitive types such as writeInt, writeShort, writeDouble, writeLong, writeBoolean etc.

You can get the length of the file using length() method and you can set the length or truncate file using setLength() method.

You can get the current position of pointer from the beginning of the file by calling getFilePointer() method. You can set the current position by calling seek() method and passing position value from beginning of the file. Certain number of bytes can be skipped by called skip() method and passing number of bytes to it.

Reading Files Randomly using RandomAccessFile

Below example opens file for read only and reads byte at a time. It shows that file pointer points to 0, as read() is called it increases and in the end it points to end of the file.

		try(RandomAccessFile raf =  new RandomAccessFile(file, "r")){		
			
			System.out.println("position: "+raf.getFilePointer());
			
			int cb= 0;
			while((cb = raf.read()) != -1) {
				System.out.println((char)cb);
			}
			System.out.println("position: "+raf.getFilePointer());

		} catch (IOException e) {
			e.printStackTrace();
		}

You can set pointer position to somewhere in the middle and read from there. For example, read last 10 bytes.

	try(RandomAccessFile raf =  new RandomAccessFile(file, "r")){		
		
		//set point to before last 10th byte
		raf.seek(raf.length()-10);	
		System.out.println("position: "+raf.getFilePointer());
		
		//read last 10 bytes
		byte db[] = new byte[10];
		raf.read(db);	
		System.out.println("content: "+ new String(db));
		//pointer points to last byte
		System.out.println("position: "+raf.getFilePointer());

	} catch (IOException e) {
		e.printStackTrace();
	}

You can set the length of contents of a file using setLength() method. You can reduce, truncate or expand the file using the method. For example, you can remove last n number of bytes. You need to open the file for write access in order to use setLength() method, otherwise, you will get access denied IO exception.

	try(RandomAccessFile raf =  new RandomAccessFile(file, "rw")){	
		
		//length of the content of the file
		System.out.println("length : "+raf.length());
		
		//removes last 15 bytes from the file
		raf.setLength(raf.length()-15);
		
		//length after truncation
		System.out.println("length : "+raf.length());

	} catch (IOException e) {
		e.printStackTrace();
	}

You can read lines using readLine() method and read data from somewhere in the each line.

		try(RandomAccessFile raf =  new RandomAccessFile(file, "rw")){	
			String line;
			
			while((line = raf.readLine()) != null) {
				raf.seek(raf.getFilePointer()+5);
				System.out.println(line);
			}

		} catch (IOException e) {
			e.printStackTrace();
		}

You can use readUTF() method to read a string encoded in UTF-8 format. In order for the method to work, first two bytes after the current pointer should tell how many number of bytes after the two bytes should be used for decoding and returning as string. If a string is not written using writeUTF(), there is a high probability that using readUTF() to read the string will throw end of file exception (EOFEexception).

Writing Files Randomly using RandomAccessFile

Open file in rw mode to write to file using RandomAccessFile. You can write anywhere in the file by setting pointer to the position where you want to write using seek() method.

	try(RandomAccessFile raf =  new RandomAccessFile(file, "rw")){	
		
		raf.seek(raf.length() - 20);
		String offers = "get 3% cashback on purchases";
		raf.write(offers.getBytes());
		
	} catch (IOException e) {
		e.printStackTrace();
	}

Reading and writing using readUTF and writeUTF methods.

	try(RandomAccessFile raf =  new RandomAccessFile(file, "rw")){	
		
		raf.seek(20);
		String offers = "get 20% off on sports";
		raf.writeUTF(offers);
		
		raf.seek(20);
		String s = raf.readUTF();
		System.out.println(s);
		
	} catch (IOException e) {
		e.printStackTrace();
	}

SeekableByteChannel

SeekableByteChannel interface extends ByteChannel and an implementation of SeekableByteChannel is FileChannel which allows you to randomly access files, meaning it allows you to read and write the data anywhere in the file to which the channel connected to. It tracks current position and allows you to change it to move the pointer to different location in the file.

For details on channels and buffers, see Java NIO API and Files access using Java NIO2 API.

SeekableByteChannel provides methods such as position() to get and set the current position, size() returns the length of the content, truncate() method reduces or truncates the size of a file by specified amount and read() and write() methods for reading and writing.

Reading Files Randomly using SeekableByteChannel

You can randomly read file using FileChannel by setting the position to a desired location and reading content from that location or specific number of bytes.

		//read 20 bytes after 10th byte from beginning of the file
		Path filePath = Paths.get("/dev/java/core/app/offers.txt");		
		ByteBuffer bb = ByteBuffer.allocate(20);

		try (FileChannel fc = (FileChannel.open(filePath, 
				StandardOpenOption.READ))) {
			
			fc.position(10);
			fc.read(bb);
			bb.flip();
			String cont = Charset.forName("UTF-8").decode(bb).toString();
			System.out.println(cont);
		} catch (IOException ex) {
			System.out.println(ex);
		}

Writing Files Randomly using SeekableByteChannel

You can randomly write to file using FileChannel by setting the position to a desired location and writing the new content from that location.

		//write new content from last 14th byte
		Path filePath = Paths.get("/dev/java/core/app/offers.txt");
		
		String offer = "upto 99% off on select limited items";
		ByteBuffer bb = ByteBuffer.wrap(offer.getBytes());

		try (FileChannel fc = (FileChannel.open(filePath, 
				StandardOpenOption.READ,
				StandardOpenOption.WRITE))) {
			
			fc.position(fc.size() - 14);
			bb.rewind();
			fc.write(bb);
		} catch (IOException ex) {
			System.out.println(ex);
		}

Other Tutorials Related to IO