NIO
The NIO system is built on two foundational items: buffers and channels.
A buffer holds data. A channel represents an open connection to a file or a socket.
To use the NIO system, you obtain a channel to a file and a buffer to hold data. You then operate on the buffer.
Buffers
Buffers are defined in the java.nio package.
All buffers are subclasses of the Buffer class. Buffer class defines the core functionality common to all buffers: current position, limit, and capacity.
The following specific buffer classes are derived from Buffer.
- ByteBuffer
- CharBuffer
- DoubleBuffer
- FloatBuffer
- IntBuffer
- LongBuffer
- MappedByteBuffer
- ShortBuffer
MappedByteBuffer is a subclass of ByteBuffer that is used to map a file to a buffer.
Channels
Channels are defined in java.nio.channels. A channel represents an open connection to an I/O source. You obtain a channel by calling getChannel( ) on an object that supports channels.
getChannel( ) is supported by following I/O classes.
- DatagramSocket
- FileInputStream
- FileOutputStream
- RandomAccessFile
- ServerSocket
- Socket
Charsets and Selectors
A charset defines the way that bytes are mapped to characters.
You can encode a sequence of characters into bytes using an encoder. You can decode a sequence of bytes into characters using a decoder. Charsets, encoders, and decoders are supported by classes defined in the java.nio.charset package.
selectors can perform I/O through multiple channels.
Reading a File
The following code reads a file by manually allocating a buffer and then performing an explicit read operation.
It opens the file for input using FileInputStream. Then, obtain a channel to this file by calling getChannel( ).
import java.io.FileInputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public class Main {
public static void main(String args[]) throws Exception {
FileInputStream fIn = new FileInputStream("test.txt");
FileChannel fChan = fIn.getChannel();
long fSize = fChan.size();
ByteBuffer mBuf = ByteBuffer.allocate((int) fSize);
fChan.read(mBuf);
mBuf.rewind();
for (int i = 0; i < fSize; i++){
System.out.println((char) mBuf.get());
}
fChan.close();
fIn.close();
}
}
The following code uses a mapped file, which automates the process of read a file. The buffer automatically contains the contents of the file.
import java.io.FileInputStream;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
public class Main {
public static void main(String args[]) throws Exception {
FileInputStream fIn = new FileInputStream("test.txt");
FileChannel fChan = fIn.getChannel();
long fSize = fChan.size();
MappedByteBuffer mBuf = fChan.map(FileChannel.MapMode.READ_ONLY, 0, fSize);
for (int i = 0; i < fSize; i++) {
System.out.println((char) mBuf.get());
}
fChan.close();
fIn.close();
}
}
Writing to a File
The following code write data to an output file through a channel, by using explicit write operations.
import java.io.FileOutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public class Main {
public static void main(String args[]) throws Exception {
FileOutputStream fOut = new FileOutputStream("test.txt");
FileChannel fChan = fOut.getChannel();
ByteBuffer mBuf = ByteBuffer.allocateDirect(26);
for (int i = 0; i < 26; i++){
mBuf.put((byte) ('A' + i));
}
mBuf.rewind();
fChan.write(mBuf);
fChan.close();
fOut.close();
}
}
The following code map the file to a buffer and then write to that buffer. Changes to the buffer will automatically be reflected in the file.
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public class Main {
public static void main(String args[]) throws Exception {
RandomAccessFile fOut = new RandomAccessFile("test.txt", "rw");
FileChannel fChan = fOut.getChannel();
ByteBuffer mBuf = fChan.map(FileChannel.MapMode.READ_WRITE, 0, 26);
for (int i = 0; i < 26; i++){
mBuf.put((byte) ('A' + i));
}
fChan.close();
fOut.close();
}
}
Copying a File Using NIO
The following program copies a file by opening an input channel to the source file and an output channel to the target file. It then writes the mapped input buffer to the output file in a single operation.
// Copy a file using NIO.
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
public class Main {
public static void main(String args[]) throws Exception {
FileInputStream fIn = new FileInputStream(args[0]);
FileOutputStream fOut = new FileOutputStream(args[1]);
FileChannel fIChan = fIn.getChannel();
FileChannel fOChan = fOut.getChannel();
long fSize = fIChan.size();
MappedByteBuffer mBuf = fIChan.map(FileChannel.MapMode.READ_ONLY, 0, fSize);
fOChan.write(mBuf); // this copies the file
fIChan.close();
fIn.close();
fOChan.close();
fOut.close();
}
}