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();
  }
}
Home 
  Java Book 
    File Stream  

Introduction:
  1. The Stream Classes
  2. The Byte Streams
  3. The Character Streams
  4. NIO