Category: 12. Java NIO

https://cdn-icons-png.flaticon.com/512/226/226777.png

  • ServerSocket Channel

    Java NIO server socket channel is again a selectable type channel used for stream oriented data flow connecting sockets.Server Socket channel can be created by invoking its static open() method,providing any pre-existing socket is not already present.Server Socket channel is created by invoking open method but not yet bound.In order to bound socket channel bind() method is to be called.

    One point to be mentioned here is if channel is not bound and any I/O operation is tried to be attempted then NotYetBoundException is thrown by this channel.So one must be ensure that channel is bounded before performing any IO operation.

    Incoming connections for the server socket channel are listen by calling the ServerSocketChannel.accept() method. When the accept() method returns, it returns a SocketChannel with an incoming connection. Thus, the accept() method blocks until an incoming connection arrives.If the channel is in non-blocking mode then accept method will immediately return null if there are no pending connections. Otherwise it will block indefinitely until a new connection is available or an I/O error occurs.

    The new channel’s socket is initially unbound; it must be bound to a specific address via one of its socket’s bind methods before connections can be accepted.Also the new channel is created by invoking the openServerSocketChannel method of the system-wide default SelectorProvider object.

    Like socket channel server socket channel could read data using read() method.Firstly the buffer is allocated. The data read from a ServerSocketChannel is stored into the buffer.Secondly we call the ServerSocketChannel.read() method and it reads the data from a ServerSocketChannel into a buffer. The integer value of the read() method returns how many bytes were written into the buffer

    Similarly data could be written to server socket channel using write() method using buffer as a parameter.Commonly uses write method in a while loop as need to repeat the write() method until the Buffer has no further bytes available to write.

    Important methods of Socket channel

    • bind(SocketAddress local) − This method is used to bind the socket channel to the local address which is provided as the parameter to this method.
    • accept() − This method is used to accepts a connection made to this channel’s socket.
    • connect(SocketAddress remote) − This method is used to connect the socket to the remote address.
    • finishConnect() − This method is used to finishes the process of connecting a socket channel.
    • getRemoteAddress() − This method return the address of remote location to which the channel’s socket is connected.
    • isConnected() − As already mentioned this method returns the status of connection of socket channel i.e whether it is connected or not.
    • open() − Open method is used open a socket channel for no specified address.This convenience method works as if by invoking the open() method, invoking the connect method upon the resulting server socket channel, passing it remote, and then returning that channel.
    • read(ByteBuffer dst) − This method is used to read data from the given buffer through socket channel.
    • setOption(SocketOption<T> name, T value) − This method sets the value of a socket option.
    • socket() − This method retrieves a server socket associated with this channel.
    • validOps() − This method returns an operation set identifying this channel’s supported operations.Server-socket channels only support the accepting of new connections, so this method returns SelectionKey.OP_ACCEPT.

    Example

    The following example shows the how to send data from Java NIO ServerSocketChannel.

    C:/Test/temp.txt

    Hello World!
    

    Client: SocketChannelClient.java

    import java.io.IOException;
    import java.net.InetSocketAddress;
    import java.nio.ByteBuffer;
    import java.nio.channels.FileChannel;
    import java.nio.channels.ServerSocketChannel;
    import java.nio.channels.SocketChannel;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    import java.nio.file.StandardOpenOption;
    import java.util.EnumSet;
    
    public class SocketChannelClient {
       public static void main(String[] args) throws IOException {
    
      ServerSocketChannel serverSocket = null;
      SocketChannel client = null;
      serverSocket = ServerSocketChannel.open();
      serverSocket.socket().bind(new InetSocketAddress(9000));
      client = serverSocket.accept();
      System.out.println("Connection Set:  " + client.getRemoteAddress());
      Path path = Paths.get("C:/Test/temp1.txt");
      FileChannel fileChannel = FileChannel.open(path, 
         EnumSet.of(StandardOpenOption.CREATE, 
            StandardOpenOption.TRUNCATE_EXISTING,
            StandardOpenOption.WRITE)
         );      
      ByteBuffer buffer = ByteBuffer.allocate(1024);
      while(client.read(buffer) &gt; 0) {
         buffer.flip();
         fileChannel.write(buffer);
         buffer.clear();
      }
      fileChannel.close();
      System.out.println("File Received");
      client.close();
    } }

    Output

    Running the client will not print anything until server starts.

    
    
    
    
    

    Server: SocketChannelServer.java

    import java.io.IOException;
    import java.net.InetSocketAddress;
    import java.net.SocketAddress;
    import java.nio.ByteBuffer;
    import java.nio.channels.FileChannel;
    import java.nio.channels.SocketChannel;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    
    public class SocketChannelServer {
       public static void main(String[] args) throws IOException {
    
      SocketChannel server = SocketChannel.open();
      SocketAddress socketAddr = new InetSocketAddress("localhost", 9000);
      server.connect(socketAddr);
      Path path = Paths.get("C:/Test/temp.txt");
      FileChannel fileChannel = FileChannel.open(path);
      ByteBuffer buffer = ByteBuffer.allocate(1024);
      while(fileChannel.read(buffer) &gt; 0) {
         buffer.flip();
         server.write(buffer);
         buffer.clear();
      }
      fileChannel.close();
      System.out.println("File Sent");
      server.close();
    } }

    Output

    Running the server will print the following.

    Connection Set:  /127.0.0.1:49558
    File Received
    
  • Socket Channel

    Java NIO socket channel is a selectable type channel which means it can be multiplexed using selector, used for stream oriented data flow connecting sockets.Socket channel can be created by invoking its static open() method,providing any pre-existing socket is not already present.Socket channel is created by invoking open method but not yet connected.In order to connect socket channel connect() method is to be called.One point to be mentioned here is if channel is not connected and any I/O operation is tried to be attempted then NotYetConnectedException is thrown by this channel.So one must be ensure that channel is connected before performing any IO operation.Once channel is get connected,it remains connected until it is closed.The state of socket channel may be determined by invoking its isConnected method.

    The connection of socket channel could be finished by invoking its finishConnect() method.Whether or not a connection operation is in progress may be determined by invoking the isConnectionPending method.By default socket channel supports non-blocking connection.Also it support asynchronous shutdown, which is similar to the asynchronous close operation specified in the Channel class.

    Socket channels are safe for use by multiple concurrent threads. They support concurrent reading and writing, though at most one thread may be reading and at most one thread may be writing at any given time. The connect and finishConnect methods are mutually synchronized against each other, and an attempt to initiate a read or write operation while an invocation of one of these methods is in progress will block until that invocation is complete.

    Important methods of Socket channel

    • bind(SocketAddress local) − This method is used to bind the socket channel to the local address which is provided as the parameter to this method.
    • connect(SocketAddress remote) − This method is used to connect the socket to the remote address.
    • finishConnect() − This method is used to finishes the process of connecting a socket channel.
    • getRemoteAddress() − This method return the address of remote location to which the channel’s socket is connected.
    • isConnected() − As already mentioned this method returns the status of connection of socket channel i.e whether it is connected or not.
    • open() and open((SocketAddress remote) − Open method is used open a socket channel for no specified address while parameterized open method open channel for specified remote address and also connects to it.This convenience method works as if by invoking the open() method, invoking the connect method upon the resulting socket channel, passing it remote, and then returning that channel.
    • read(ByteBuffer dst) − This method is used to read data from the given buffer through socket channel.
    • isConnectionPending() − This method tells whether or not a connection operation is in progress on this channel.

    Example

    The following example shows the how to send data from Java NIO SocketChannel.

    C:/Test/temp.txt

    Hello World!
    

    Client: SocketChannelClient.java

    import java.io.IOException;
    import java.net.InetSocketAddress;
    import java.nio.ByteBuffer;
    import java.nio.channels.FileChannel;
    import java.nio.channels.ServerSocketChannel;
    import java.nio.channels.SocketChannel;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    import java.nio.file.StandardOpenOption;
    import java.util.EnumSet;
    
    public class SocketChannelClient {
       public static void main(String[] args) throws IOException {
    
      ServerSocketChannel serverSocket = null;
      SocketChannel client = null;
      serverSocket = ServerSocketChannel.open();
      serverSocket.socket().bind(new InetSocketAddress(9000));
      client = serverSocket.accept();
      System.out.println("Connection Set:  " + client.getRemoteAddress());
      Path path = Paths.get("C:/Test/temp1.txt");
      FileChannel fileChannel = FileChannel.open(path, 
         EnumSet.of(StandardOpenOption.CREATE, 
            StandardOpenOption.TRUNCATE_EXISTING,
            StandardOpenOption.WRITE)
         );      
      ByteBuffer buffer = ByteBuffer.allocate(1024);
      while(client.read(buffer) &gt; 0) {
         buffer.flip();
         fileChannel.write(buffer);
         buffer.clear();
      }
      fileChannel.close();
      System.out.println("File Received");
      client.close();
    } }

    Output

    Running the client will not print anything until server starts.

    
    
    
    
    

    Server: SocketChannelServer.java

    import java.io.IOException;
    import java.net.InetSocketAddress;
    import java.net.SocketAddress;
    import java.nio.ByteBuffer;
    import java.nio.channels.FileChannel;
    import java.nio.channels.SocketChannel;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    
    public class SocketChannelServer {
       public static void main(String[] args) throws IOException {
    
      SocketChannel server = SocketChannel.open();
      SocketAddress socketAddr = new InetSocketAddress("localhost", 9000);
      server.connect(socketAddr);
      Path path = Paths.get("C:/Test/temp.txt");
      FileChannel fileChannel = FileChannel.open(path);
      ByteBuffer buffer = ByteBuffer.allocate(1024);
      while(fileChannel.read(buffer) &gt; 0) {
         buffer.flip();
         server.write(buffer);
         buffer.clear();
      }
      fileChannel.close();
      System.out.println("File Sent");
      server.close();
    } }

    Output

    Running the server will print the following.

    Connection Set:  /127.0.0.1:49558
    File Received
    
  • Datagram Channel

    Java NIO Datagram is used as channel which can send and receive UDP packets over a connection less protocol.By default datagram channel is blocking while it can be use in non blocking mode.In order to make it non-blocking we can use the configureBlocking(false) method.DataGram channel can be open by calling its one of the static method named as open() which can also take IP address as parameter so that it can be used for multi casting.

    Datagram channel alike of FileChannel do not connected by default in order to make it connected we have to explicitly call its connect() method.However datagram channel need not be connected in order for the send and receive methods to be used while it must be connected in order to use the read and write methods, since those methods do not accept or return socket addresses.

    We can check the connection status of datagram channel by calling its isConnected() method.Once connected, a datagram channel remains connected until it is disconnected or closed.Datagram channels are thread safe and supports multi-threading and concurrency simultaneously.

    Important methods of datagram channel

    • bind(SocketAddress local) − This method is used to bind the datagram channel’s socket to the local address which is provided as the parameter to this method.
    • connect(SocketAddress remote) − This method is used to connect the socket to the remote address.
    • disconnect() − This method is used to disconnect the socket to the remote address.
    • getRemoteAddress() − This method return the address of remote location to which the channel’s socket is connected.
    • isConnected() − As already mentioned this method returns the status of connection of datagram channel i.e whether it is connected or not.
    • open() and open(ProtocolFamily family) − Open method is used open a datagram channel for single address while parametrized open method open channel for multiple addresses represented as protocol family.
    • read(ByteBuffer dst) − This method is used to read data from the given buffer through datagram channel.
    • receive(ByteBuffer dst) − This method is used to receive datagram via this channel.
    • send(ByteBuffer src, SocketAddress target) − This method is used to send datagram via this channel.

    Example

    The following example shows the how to send data from Java NIO DataGramChannel.

    Server: DatagramChannelServer.java

    import java.io.IOException;
    import java.net.InetSocketAddress;
    import java.net.SocketAddress;
    import java.nio.ByteBuffer;
    import java.nio.channels.DatagramChannel;
    
    public class DatagramChannelServer {
       public static void main(String[] args) throws IOException {
    
      DatagramChannel server = DatagramChannel.open();
      InetSocketAddress iAdd = new InetSocketAddress("localhost", 8989);
      server.bind(iAdd);
      System.out.println("Server Started: " + iAdd);
      ByteBuffer buffer = ByteBuffer.allocate(1024);
      //receive buffer from client.
      SocketAddress remoteAdd = server.receive(buffer);
      //change mode of buffer
      buffer.flip();
      int limits = buffer.limit();
      byte bytes&#91;] = new byte&#91;limits];
      buffer.get(bytes, 0, limits);
      String msg = new String(bytes);
      System.out.println("Client at " + remoteAdd + "  sent: " + msg);
      server.send(buffer,remoteAdd);
      server.close();
    } }

    Output

    Server Started: localhost/127.0.0.1:8989
    

    Client: DatagramChannelClient.java

    import java.io.IOException;
    import java.net.InetSocketAddress;
    import java.net.SocketAddress;
    import java.nio.ByteBuffer;
    import java.nio.channels.DatagramChannel;
    
    public class DatagramChannelClient {
       public static void main(String[] args) throws IOException {
    
      DatagramChannel client = null;
      client = DatagramChannel.open();
      client.bind(null);
      String msg = "Hello World!";
      ByteBuffer buffer = ByteBuffer.wrap(msg.getBytes());
      InetSocketAddress serverAddress = new InetSocketAddress("localhost",
        8989);
      client.send(buffer, serverAddress);
      buffer.clear();
      client.receive(buffer);
      buffer.flip();
    
      client.close();
    } }

    Output

    Running the client will print the following output on server.

    Server Started: localhost/127.0.0.1:8989
    Client at /127.0.0.1:64857  sent: Hello World!
    
  • File Channel

    Description

    As already mentioned FileChannel implementation of Java NIO channel is introduced to access meta data properties of the file including creation, modification, size etc.Along with this File Channels are multi threaded which again makes Java NIO more efficient than Java IO.

    In general we can say that FileChannel is a channel that is connected to a file by which you can read data from a file, and write data to a file.Other important characteristic of FileChannel is this that it cannot be set into non-blocking mode and always runs in blocking mode.

    We can’t get file channel object directly, Object of file channel is obtained either by −

    • getChannel() − method on any either FileInputStream, FileOutputStream or RandomAccessFile.
    • open() − method of File channel which by default open the channel.

    The object type of File channel depends on type of class called from object creation i.e if object is created by calling getchannel method of FileInputStream then File channel is opened for reading and will throw NonWritableChannelException in case attempt to write to it.

    Example

    The following example shows the how to read and write data from Java NIO FileChannel.

    Following example reads from a text file from C:/Test/temp.txt and prints the content to the console.

    temp.txt

    Hello World!
    

    FileChannelDemo.java

    import java.io.IOException;
    import java.io.RandomAccessFile;
    import java.nio.ByteBuffer;
    import java.nio.channels.FileChannel;
    import java.nio.charset.Charset;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    import java.nio.file.StandardOpenOption;
    import java.util.HashSet;
    import java.util.Set;
    
    public class FileChannelDemo {
       public static void main(String args[]) throws IOException {
    
      //append the content to existing file 
      writeFileChannel(ByteBuffer.wrap("Welcome to TutorialsPoint".getBytes()));
      //read the file
      readFileChannel();
    } public static void readFileChannel() throws IOException {
      RandomAccessFile randomAccessFile = new RandomAccessFile("C:/Test/temp.txt",
      "rw");
      FileChannel fileChannel = randomAccessFile.getChannel();
      ByteBuffer byteBuffer = ByteBuffer.allocate(512);
      Charset charset = Charset.forName("US-ASCII");
      while (fileChannel.read(byteBuffer) &gt; 0) {
         byteBuffer.rewind();
         System.out.print(charset.decode(byteBuffer));
         byteBuffer.flip();
      }
      fileChannel.close();
      randomAccessFile.close();
    } public static void writeFileChannel(ByteBuffer byteBuffer)throws IOException {
      Set&lt;StandardOpenOption&gt; options = new HashSet&lt;&gt;();
      options.add(StandardOpenOption.CREATE);
      options.add(StandardOpenOption.APPEND);
      Path path = Paths.get("C:/Test/temp.txt");
      FileChannel fileChannel = FileChannel.open(path, options);
      fileChannel.write(byteBuffer);
      fileChannel.close();
    } }

    Learn Java in-depth with real-world projects through our Java certification course. Enroll and become a certified expert to boost your career.

    Output

    Hello World! Welcome to TutorialsPoint
    
  • Channels

    Description

    As name suggests channel is used as mean of data flow from one end to other.Here in java NIO channel act same between buffer and an entity at other end in other words channel are use to read data to buffer and also write data from buffer.

    Unlike from streams which are used in conventional Java IO channels are two way i.e can read as well as write.Java NIO channel supports asynchronous flow of data both in blocking and non blocking mode.

    Implementations of Channel

    Java NIO channel is implemented primarily in following classes −

    • FileChannel − In order to read data from file we uses file channel. Object of file channel can be created only by calling the getChannel() method on file object as we can’t create file object directly.
    • DatagramChannel − The datagram channel can read and write the data over the network via UDP (User Datagram Protocol).Object of DataGramchannel can be created using factory methods.
    • SocketChannel − The SocketChannel channel can read and write the data over the network via TCP (Transmission Control Protocol). It also uses the factory methods for creating the new object.
    • ServerSocketChannel − The ServerSocketChannel read and write the data over TCP connections, same as a web server. For every incoming connection a SocketChannel is created.

    Learn Java in-depth with real-world projects through our Java certification course. Enroll and become a certified expert to boost your career.

    Example

    Following example reads from a text file from C:/Test/temp.txt and prints the content to the console.

    temp.txt

    Hello World!
    

    ChannelDemo.java

    import java.io.IOException;
    import java.io.RandomAccessFile;
    import java.nio.ByteBuffer;
    import java.nio.channels.FileChannel;
    public class ChannelDemo {
       public static void main(String args[]) throws IOException {
    
      RandomAccessFile file = new RandomAccessFile("C:/Test/temp.txt", "r");
      FileChannel fileChannel = file.getChannel();
      ByteBuffer byteBuffer = ByteBuffer.allocate(512);
      while (fileChannel.read(byteBuffer) &gt; 0) {
         // flip the buffer to prepare for get operation
         byteBuffer.flip();
         while (byteBuffer.hasRemaining()) {
            System.out.print((char) byteBuffer.get());
         }
      }
      file.close();
    } }

    Output

    Hello World!
    
  • NIO vs IO

    As we know that java NIO is introduced for advancement of conventional java IO API.The main enhancements which make NIO more efficient than IO are channel data flow model used in NIO and use of operating system for conventional IO tasks.

    The difference between Java NIO and Java IO can be explained as following −

    • As mentioned in previous post in NIO buffer and channel oriented data flow for I/O operations which provide faster execution and better performance as compare to IO.Also NIO uses operating system for conventional I/O tasks which again makes it more efficient.
    • Other aspect of difference between NIO and IO is this IO uses stream line data flow i.e one more byte at a time and relies on converting data objects into bytes and vice-e-versa while NIO deals with the data blocks which are chunks of bytes.
    • In java IO stream objects are unidirectional while in NIO channels are bidirectional meaning a channel can be used for both reading and writing data.
    • The streamline data flow in IO does not allow move forth and back in the data.If case need to move forth and back in the data read from a stream need to cache it in a buffer first.While in case of NIO we uses buffer oriented which allows to access data back and forth without need of caching.
    • NIO API also supports multi threading so that data can be read and written asynchronously in such as a way that while performing IO operations current thread is not blocked.This again make it more efficient than conventional java IO API.
    • Concept of multi threading is introduced with the introduction of Selectors in java NIO which allow to listen to multiple channels for IO events in asynchronous or non blocking way.
    • Multi threading in NIO make it Non blocking which means that thread is requested to read or write only when data is available otherwise thread can be used in other task for mean time.But this is not possible in case of conventional java IO as no multi threading is supported in it which make it as Blocking.
    • NIO allows to manage multiple channels using only a single thread,but the cost is that parsing the data might be somewhat more complicated than when reading data from a blocking stream in case of java IO.So in case fewer connections with very high bandwidth are required with sending a lot of data at a time,than in this case java IO API might be the best fit.
  • Environment Setup

    This section guides you on how to download and set up Java on your machine. Please follow the following steps to set up the environment.

    Java SE is freely available from the link Download Java. So you download a version based on your operating system.

    Follow the instructions to download java and run the .exe to install Java on your machine. Once you installed Java on your machine, you would need to set environment variables to point to correct installation directories −

    Setting up the path for windows 2000/XP

    Assuming you have installed Java in c:\Program Files\java\jdk directory −

    • Right-click on ‘My Computer’ and select ‘Properties’.
    • Click on the ‘Environment variables’ button under the ‘Advanced’ tab.
    • Now alter the ‘Path’ variable so that it also contains the path to the Java executable. Example, if the path is currently set to ‘C:\WINDOWS\SYSTEM32’, then change your path to read ‘C:\WINDOWS\SYSTEM32;c:\Program Files\java\jdk\bin’.

    Setting up the path for windows 95/98/ME

    Assuming you have installed Java in c:\Program Files\java\jdk directory −

    • Edit the ‘C:\autoexec.bat’ file and add the following line at the end:
      ‘SET PATH = %PATH%;C:\Program Files\java\jdk\bin’

    Learn Java in-depth with real-world projects through our Java certification course. Enroll and become a certified expert to boost your career.

    Setting up the path for Linux, UNIX, Solaris, FreeBSD

    Environment variable PATH should be set to point to where the java binaries have been installed. Refer to your shell documentation if you have trouble doing this.

    Example, if you use bash as your shell, then you would add the following line to the end of your ‘.bashrc: export PATH = /path/to/java:$PATH’

    Popular Java Editors

    To write your java programs you will need a text editor. There are even more sophisticated IDE available in the market. But for now, you can consider one of the following −

    • Notepad − On Windows machine you can use any simple text editor like Notepad (Recommended for this tutorial), TextPad.
    • Netbeans − is a Java IDE that is open source and free which can be downloaded from http://www.netbeans.org/index.html.
    • Eclipse − is also a java IDE developed by the eclipse open source community and can be downloaded from https://www.eclipse.org/.
  • Overview

    Java.nio package was introduced in java 1.4. In contrast of java I/O in java NIO the buffer and channel oriented data flow for I/O operations is introduced which in result provide faster execution and better performance.

    Also NIO API offer selectors which introduces the functionality of listen to multiple channels for IO events in asynchronous or non blocking way.In NIO the most time-consuming I/O activities including filling and draining of buffers to the operating system which increases in speed.

    The central abstractions of the NIO APIs are following −

    • Buffers,which are containers for data,charsets and their associated decoders and encoders,which translate between bytes and Unicode characters.
    • Channels of various types,which represent connections to entities capable of performing I/O operations
    • Selectors and selection keys, which together with selectable channels define a multiplexed, non-blocking I/O facility.