In the past, I have talked about RandomAccessFile and how it can be used for doing faster IO in Java, and in this Java NIO tutorial, we are going to see how to use read/write data from using FileChannel and ByteBuffer. Channel provides an alternate way to read data from a file, it provides better performance than InputStream or OutputStream. It can also be opened in blocking and non-blocking mode. Though FileChannles are read/write channels and they are always blocking, they cannot be put into non-blocking mode.
The RandomAccessFile class treats a file as an array of Bytes. You can write your data in any position of the Array and you can read from any position. To do that, it uses a pointer that holds the current position and provides several methods like seek() to move that pointer.
Once you are in the right position, you can get the FileChannel from RandomAccessFile and starting reading data from a file. By the way, JDK 7 also introduced NIO 2, which makes dealing with files and directories even easier.
And, If you are new to the Java world then I also recommend you go through The Complete Java MasterClass on Udemy to learn Java in a better and more structured way. This is one of the best and up-to-date courses to learn Java online.
Similarly, in the case of a read, a channel puts data in a buffer you provide a file, network, or any other source. Since the same buffer is used for reading and writing i.e. you write data into the buffer but the channel reads it for writing into the file, you must call the flip() method once you are done writing into the buffer.
The flip() method changes the pointers and allows you to read data from the buffer. There are three types of buffer in Java, direct, non-direct, and mapped buffer. We will use the direct byte buffer in this example.
Another important point to note is that you can use the same buffer for reading and writing, but you need to flip it. Now, let's see a sample Java program to read/write data from files using FileChannel and ByteBuffer in Java. After Memory Mapped File, this is the second-fastest way to read and write from a file in Java.
Any object which implements this interface can be saved and loaded, but how do you save and load them is left to the implementor i.e. you can use Chanel and Buffer like we have done or you can use the old approach to read/write a file in Java.
Our interface to abstract reading and writing mechanism. This is also the actual use of the interface, provide abstraction, separating what to do from how to do it. Like this interface just say persist and recover, doesn't say how you do that.
Concrete class to implement Persistable to make them readable and writable
Similarly, after reading data from the file into the buffer, flip it again so that you can read data from a buffer to the popular contents of an object. Many Java programmer does this mistake of not flipping after writing and ends up debugging hours because either nothing is written to file or nothing they can read from a file.
That's all about how to read/write a File using FileChannel and ByteBuffer in Java. In this demon, I have shown you how to read and write a RandomAccessFile using FileChannel and ByteBuffer, but you can apply the same technique to read any other text or binary file from the Java program.
Other Java IO tutorials you may like:
Thanks for reading this article so far. If you like this Java FileChannel Tutorial and Example then please share with your friends and colleagues. If you have any questions or feedback, please ask.
The RandomAccessFile class treats a file as an array of Bytes. You can write your data in any position of the Array and you can read from any position. To do that, it uses a pointer that holds the current position and provides several methods like seek() to move that pointer.
Once you are in the right position, you can get the FileChannel from RandomAccessFile and starting reading data from a file. By the way, JDK 7 also introduced NIO 2, which makes dealing with files and directories even easier.
And, If you are new to the Java world then I also recommend you go through The Complete Java MasterClass on Udemy to learn Java in a better and more structured way. This is one of the best and up-to-date courses to learn Java online.
How to read/write files using FileChannel and ByteBuffer
Before start coding, let's revise the basic concept of Channel and Buffer in Java NIO. In one word, buffers work with the channel. Channels are the tube through which data is transferred and buffers are the source and target of those data transfers. In the case of a write, data you want to write is placed in a buffer, which is passed to a channel then the channel reads that data from the buffer and writes it into the file.Similarly, in the case of a read, a channel puts data in a buffer you provide a file, network, or any other source. Since the same buffer is used for reading and writing i.e. you write data into the buffer but the channel reads it for writing into the file, you must call the flip() method once you are done writing into the buffer.
The flip() method changes the pointers and allows you to read data from the buffer. There are three types of buffer in Java, direct, non-direct, and mapped buffer. We will use the direct byte buffer in this example.
Steps to read/write data using FileChannel and Buffer
Here is the step by step guide to starting reading data from a file using RandomAccessFile, FileChannel, and ByteBuffer:- Open the file you want to read/write using RandomAccessFile in read/write mode.
- Call the getChannel() method of RandomAccessFile to get the FileChannel. The position of the returned channel will always be equal to this object's file-pointer offset as returned by the getFilePointer() method.
- Create a ByteBuffer using ByteBuffer.allocate() method.
- Store the data into ByteBuffer using various put() method e.g. putInt(), putLong().
- Flip the Buffer so that Channel can read data from the buffer and write it into a file. The flip() method changes the pointers and allows you to read data from the buffer.
- Call the write() method of FileChannel.
- Close the FileChannel
- Close the RandomAccessFile.
Another important point to note is that you can use the same buffer for reading and writing, but you need to flip it. Now, let's see a sample Java program to read/write data from files using FileChannel and ByteBuffer in Java. After Memory Mapped File, this is the second-fastest way to read and write from a file in Java.
Java Program to read/writes from a file using FileChannel and ByteBuffer
Here is a sample program to demonstrate how you can read and write data from a file (can be binary or text file) using FileChannel and ByteBuffer class. I have also used abstraction to create an interface called Persistable, which provides two methods persist() and recover().Any object which implements this interface can be saved and loaded, but how do you save and load them is left to the implementor i.e. you can use Chanel and Buffer like we have done or you can use the old approach to read/write a file in Java.
import java.io.FileNotFoundException; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; /** * Java Program to read and write on RandomAccessFile in Java * using FileChannle and ByteBuffer. * * @author Javin */ public class FileChannelDemo { public static void main(String args[]) { Tablet ipad = new Tablet("Apple", true, 1000); System.out.println("Writing into RandomAcessFile : " + ipad); write("tablet.store", ipad); Tablet fromStore = new Tablet(); read("tablet.store", fromStore); System.out.println("Object read from RandomAcessFile : " + fromStore); } /* * Method to write data into File using FileChannel and ByteBuffeer */ public static void write(String filename, Persistable object) { try { // Creating RandomAccessFile for writing RandomAccessFile store = new RandomAccessFile("tablet", "rw"); // getting FileChannel from file FileChannel channel = store.getChannel(); // creating and initializing ByteBuffer for reading/writing data ByteBuffer buffer = ByteBuffer.allocate(2048); // an instance of Persistable writing into ByteBuffer object.persist(buffer); // flip the buffer for writing into file buffer.flip(); int numOfBytesWritten = channel.write(buffer); // writing into File System.out.println("number of bytes written : " + numOfBytesWritten); channel.close(); // closing file channel store.close(); // closing RandomAccess file } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } /* * Method to read data from File using FileChannel and ByteBuffeer */ public static void read(String filename, Persistable object) { try { // Opening RandomAccessFile for reading data RandomAccessFile store = new RandomAccessFile("tablet", "rw"); // getting file channel FileChannel channel = store.getChannel(); // preparing buffer to read data from file ByteBuffer buffer = ByteBuffer.allocate(1024); // reading data from file channel into buffer int numOfBytesRead = channel.read(buffer); System.out.println("number of bytes read : " + numOfBytesRead); // You need to filp the byte buffer before reading buffer.flip(); // Recovering object object.recover(buffer); channel.close(); store.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
Our interface to abstract reading and writing mechanism. This is also the actual use of the interface, provide abstraction, separating what to do from how to do it. Like this interface just say persist and recover, doesn't say how you do that.
interface Persistable { public void persist(ByteBuffer buffer); public void recover(ByteBuffer buffer); }
Concrete class to implement Persistable to make them readable and writable
class Tablet implements Persistable { private String brand; private boolean isCellular; private long cost; // in US Dollars public Tablet() { brand = ""; } public Tablet(String brand, boolean isCellular, long cost) { this.brand = brand; this.isCellular = isCellular; this.cost = cost; } public final String getBrand() { return brand; } public final boolean isCellular() { return isCellular; } public final long getCost() { return cost; } public final void setBrand(String brand) { this.brand = brand; } public final void setCellular(boolean isCellular) { this.isCellular = isCellular; } public final void setCost(long cost) { this.cost = cost; } @Override public void persist(ByteBuffer buffer) { byte[] strBytes = brand.getBytes(); buffer.putInt(strBytes.length); buffer.put(strBytes, 0, strBytes.length); buffer.put(isCellular == true ? (byte) 1 : (byte) 0); buffer.putLong(cost); } @Override public void recover(ByteBuffer buffer) { int size = buffer.getInt(); byte[] rawBytes = new byte[size]; buffer.get(rawBytes, 0, size); this.brand = new String(rawBytes); this.isCellular = buffer.get() == 1 ? true : false; this.cost = buffer.getLong(); } @Override public String toString() { return "Tablet [brand=" + brand + ", isCellular=" + isCellular + ", cost=" + cost + "]"; } } Output: Writing into RandomAcessFile : Tablet [brand=Apple, isCellular=true, cost=1000] number of bytes written : 18 number of bytes read : 1024 Object read from RandomAcessFile : Tablet [brand=Apple, isCellular=true, cost=1000]
Caution
Don't forget to flip the byte buffer after writing the contents of the object into it, because the file channel needs to read it in order to write data into RandomAccessFile. If you forget to call the flip() method before calling the FileChannel.write() then you end up writing nothing into the file.Similarly, after reading data from the file into the buffer, flip it again so that you can read data from a buffer to the popular contents of an object. Many Java programmer does this mistake of not flipping after writing and ends up debugging hours because either nothing is written to file or nothing they can read from a file.
That's all about how to read/write a File using FileChannel and ByteBuffer in Java. In this demon, I have shown you how to read and write a RandomAccessFile using FileChannel and ByteBuffer, but you can apply the same technique to read any other text or binary file from the Java program.
Other Java IO tutorials you may like:
- How to read the file in one line in Java 8? (solution)
- How to read the file line by line in Java using BufferedReader and Scanner? (answer)
- How to read/write an Excel file in Java? (program)
- How to read CSV files in Java? (program)
- How to append data into an existing file in Java? (answer)
Thanks for reading this article so far. If you like this Java FileChannel Tutorial and Example then please share with your friends and colleagues. If you have any questions or feedback, please ask.
No comments :
Post a Comment