New I/O, usually called NIO, is a collection of APIs that offer additional capabilities for intensive I/O operations. It was introduced with the Java 1.4 release by Sun Microsystems to complement an existing standard I/O. The extended NIO that offers further new file system APIs, called NIO2, was released with Java SE 7 (“Dolphin”).
NIO related questions are very popular in java interviews now-a-days.
NIO2 provides two major methods of reading a file:
- Using buffer and channel classes
- Using Path and Files classes
In this post, I am showing a couple of ways to read a file from file system. So lets start them by first showing old famous approach first, so that we can see what really changed.
Old famous I/O way
This example shows how we have been reading a text file using old I/O library APIs. It uses a BufferedReader object for reading. Another way can be using InputStream implementation.
package com.howtodoinjava.test.nio; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; public class WithoutNIOExample { public static void main(String[] args) { BufferedReader br = null; String sCurrentLine = null; try { br = new BufferedReader( new FileReader("test.txt")); while ((sCurrentLine = br.readLine()) != null) { System.out.println(sCurrentLine); } } catch (IOException e) { e.printStackTrace(); } finally { try { if (br != null) br.close(); } catch (IOException ex) { ex.printStackTrace(); } } } }
1) Read a small file in buffer of file size
package com.howtodoinjava.test.nio; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; public class ReadFileWithFileSizeBuffer { public static void main(String args[]) { try { RandomAccessFile aFile = new RandomAccessFile( "test.txt","r"); FileChannel inChannel = aFile.getChannel(); long fileSize = inChannel.size(); ByteBuffer buffer = ByteBuffer.allocate((int) fileSize); inChannel.read(buffer); //buffer.rewind(); buffer.flip(); for (int i = 0; i < fileSize; i++) { System.out.print((char) buffer.get()); } inChannel.close(); aFile.close(); } catch (IOException exc) { System.out.println(exc); System.exit(1); } } }
2) Read a large file in chunks with fixed size buffer
package com.howtodoinjava.test.nio; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; public class ReadFileWithFixedSizeBuffer { public static void main(String[] args) throws IOException { RandomAccessFile aFile = new RandomAccessFile ("test.txt", "r"); FileChannel inChannel = aFile.getChannel(); ByteBuffer buffer = ByteBuffer.allocate(1024); while(inChannel.read(buffer) > 0) { buffer.flip(); for (int i = 0; i < buffer.limit(); i++) { System.out.print((char) buffer.get()); } buffer.clear(); // do something with the data and clear/compact it. } inChannel.close(); aFile.close(); } }
3) Faster file copy with mapped byte buffer
package com.howtodoinjava.test.nio; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; public class ReadFileWithMappedByteBuffer { public static void main(String[] args) throws IOException { RandomAccessFile aFile = new RandomAccessFile ("test.txt", "r"); FileChannel inChannel = aFile.getChannel(); MappedByteBuffer buffer = inChannel.map(FileChannel.MapMode.READ_ONLY, 0, inChannel.size()); buffer.load(); for (int i = 0; i < buffer.limit(); i++) { System.out.print((char) buffer.get()); } buffer.clear(); // do something with the data and clear/compact it. inChannel.close(); aFile.close(); } }
All above techniques will read the content of file and print it to console. You can do whatever you want once you have read it.
Happy Learning !!
MappedByteBuffer buffer = inChannel.map(FileChannel.MapMode.READ_ONLY, 0, inChannel.size());
—-> inChannel.size()
it looks like size of the file. What will happen if file is having 8-10 GB. Will mappedbytebuffer is suggestible and how internally it will work without out of memory
It is size of the region to be mapped. It is not buffer size.
https://docs.oracle.com/javase/7/docs/api/java/nio/channels/FileChannel.html#map%28java.nio.channels.FileChannel.MapMode,%20long,%20long%29
Nice examples. I just wonder that on your first example “1) Read a small file in buffer of file size” why did you not use finally{} block for aFile resource?
When you close the reader it will close the file for you, theoretically you would miss the case when the reader throws an exception in the constructor after the file has opened, but I believe the only exceptions that could occur at that time would be things like out of memory and similar which would forcibly close down your JVM anyways.
Hi Lokesh,
I want to divide an xml file according to size using NIO. We can read char or byte only from buffer, so how can i check whether the xml file is proper or not.
Animesh
Brilliant question. And that means I do not know the answer 🙂 I will try to find a solution for this problem when time permits. I you get any solution, then please update me as well. Thanks !!
Hi,
Could you please explain why in the example “1) Read a small file in buffer of file size”, you write:
20 buffer.rewind();
21 buffer.flip();
Wouldn’t be enough to use buffer.flip(), like in the example “2) Read a large file in chunks with fixed size buffer”?
You are right. I must have forget to comment that line. Actually both methods are almost similar. In fact, you can use rewind( ) to go back and reread the data in a buffer that has already been flipped.
How multiple threads could read single file parallely
Hi Lokesh, thanks for the informative write-up. The key difference is that in NIO you are reading a buffer not a stream. And NIO is by design non-blocking. So the thread is not blocked.
Just a question. I have to process huge text files (billions of records, each) line by line. Should I read them with IO, NIO, or NIO2? Which class?
IO is not good solution. Use ReadFileWithFixedSizeBuffer example. In java 8, you can use https://howtodoinjava.com/java8/read-file-line-by-line-in-java-8-streams-of-lines-example/
Sorry but the old famous way do not the same – here is reading line by line – and with a Reader.
The three other sources reading byte by byte – with a stream.
No good!
Dear friend, it’s not about lines or bytes or streams. It’s about how it was and how it is.
very useful
thanks