Java nio how to

Java NIO Tutorial

Java NIO (New IO) is an alternative IO API for Java, meaning alternative to the standard Java IO and Java Networking API’s. Java NIO offers a different IO programming model than the traditional IO APIs. Note: Sometimes NIO is claimed to mean Non-blocking IO. However, this is not what NIO meant originally. Also, parts of the NIO APIs are actually blocking — e.g. the file APIs — so the label «Non-blocking» would be slightly misleading.

Java NIO: Non-blocking IO

Java NIO enables you to do non-blocking IO. For instance, a thread can ask a channel to read data into a buffer. While the channel reads data into the buffer, the thread can do something else. Once data is read into the buffer, the thread can then continue processing it. The same is true for writing data to channels.

Java NIO: Channels and Buffers

In the standard IO API you work with byte streams and character streams. In NIO you work with channels and buffers. Data is always read from a channel into a buffer, or written from a buffer to a channel.

Java NIO: Selectors

Java NIO contains the concept of «selectors». A selector is an object that can monitor multiple channels for events (like: connection opened, data arrived etc.). Thus, a single thread can monitor multiple channels for data.

Читайте также:  Php set value type

Java NIO Concepts

There are several new concepts to learn in Java NIO compared to the old Java IO model. These concepts are listed below:

  • Channels
  • Buffers
  • Scatter — Gather
  • Channel to Channel Transfers
  • Selectors
  • FileChannel
  • SocketChannel
  • ServerSocketChannel
  • Non-blocking Server Design
  • DatagramChannel
  • Pipe
  • NIO vs. IO
  • Path
  • Files
  • AsynchronousFileChannel

Источник

How to use Java NIO API

In this article, we will learn how to use Java NIO API such as accessing files and directories, reading and writing text files, … They may be useful to improve performance in our project.

Table of contents

Accessing Files and Directories using Java NIO Path

  1. Introduction to Path class In the JDK 1.0, 1995 — 1996, we have a old File object. And now we have a second object that is used to interact with files and directories called as Path object. Path is an interface which is introduced in Java NIO file package during Java version 7, and is the representation of location in particular file system.
  2. The difference between Files and Paths
    • File is a class from Java 1.0 that models files, whereas Path is an interface from Java 7. It means that for each file system, for each type of file system that exists, we can have different implementation of the Path interface. The implementation for the Windows file system is not the same as Linux file system. For instance, since a File object is created on a String. It’s just a wrapper on the String that represent the path of the file system. It’s independent on any file system, and indeed, a file does not know about anything the file system. But Java 7 introduces a FileSystem class with file system objects. And path is necessarily to linked to an explicit file system. If we do not tell the system, which file system we’re going to use when we create a path, this system will give us a path and linked to our default file system, which is most of the time the case.
  3. Accessing Files with Path objects Basically, we can do the same kind of thing as with the File object. We can access file in roughly the same way, but we can get more information, especially specific attributes dependent on our FileSystem objects. The Path is just used to access file or directory on the given file system. A Path gives information on a path:
    • different elements directory that we are going to go through to access this file.
    • We can check if this element contains a symbolic link or not.
    • Through different factory methods from Files class, we can have more information on the file or directory represented by this path. Basically, the read/write property, can be executed in this file or directories exist or not.
  4. Creating Path object Due to Path is an interface, to get an instances of Path, we have to use factory method. Now, we have two pattern to create those Path instances.
    • from the Paths factory class. From the Paths factory class, there are two get() methods
      • takes a path as a String, or a vararg of paths. For example:
 Path path1 = Paths.get("C:/tmp/debug.log"); Path path2 = Paths.get("C:", "tmp", "debug.log"); 
 URI uri = URI.create("file://C:/tmp/debug.log"); Path path3 = Paths.get(uri); 
 Path path3 = Path.of("C:/tmp/debug.log"); 
  • Check if it exists or not.
  • Check if it is hidden.
  • Check if the path is a file or a directory.
  • Check if it is readable or writeable.
  • Check if it is executable.

All those functionalities are implemented using corresponding method. For instance, we have exists() method that takes a path as a parameter.

 Path path = Paths.get("C:/tmp/debug.log"); boolean exists = Files.exists(path); boolean exists = Files.exists(path, LinkOption.NOFOLLOW_LINKS); 

These methods may take a further argument which is a constant called as NOFOLLOW_LINKS . It means that the API can check if a path contains symbolic links.

And we can check if two path actually locate the same file. Those two path may be very different in the structure. But, in fact, pointing to the same element on the disk, and this is what this method is used to in this case.

 boolean sameFile = Files.isSameFile(path1, path2); 

Reading and Writing Text files using Java NIO API

  1. Introducing the possible errors when dealing with text files The difference between Binary file and Text file
    • Binary files are about storing bytes. For instance, if our bytes have to be grouped four by four to create integer, this is our interpretation, our application’s specific interpretation of the binary content of a given file.
    • Text files are about storing characters. The character is also a set of bytes in a text file, but in can be interpreted as this or that character using a Charset. There are many Charset such as ASCII, ISO 8859, UTF-8, Unicode, … The charset we should all be using is probably utf-8, but this is not the only one that is living around. So the API provide support for that.

Java provides classes to read and write both types of files.

  • The classes are provided to read and write text file such as Reader, Writer, and the further extended classes …
  • The classes for binary files are InputStream, OutputStream, …
  • get a BufferedReader — is extension of Reader class.
  • then, through this BufferedReader, we are going to read file line by line.

Belows are some steps to use the above pattern:

  • create a Path object.
  • get a BufferedReader on the corresponding file.
  • read a line (return null if there is none)
 Path path = Paths.get("C:/tmp/sometext.txt"); BufferedReader reader = Files.newBufferedReader(path); String line = reader.readLine(); 

Some problems can happens in the above case:

Then, it can throw an exception like this:

 Exception in thread "main" java.nio.charset.MalformedInputException: Input length = 1 

When we see this exception, we can find that the charset we need is not a default charset, we need to pass charset as a parameter.

 BufferedReader reader = Files.newBufferedReader(path, StandardCharsets.ISO_8859_1); 
 Path path = Paths.get("C:/tmp/sometext.txt"); BufferedWriter writer = Files.newBufferedWriter(path); writer.write("Hello, world!"); 

Some problems for the above code:

We need to call close() method of BufferedWriter instance manually or use try-with-resources to automatically close this file. Because the close() method is calling a flush() method itself. And the flush() method will transfer what has been returned to the disk.

In order to use multiple writer correctly, we need to put writers into try statement like the below code.

 Path path = Path.of(". "); try (BufferedWriter writer1 = Files.newBufferedWriter(path); BufferedWriter writer2 = Files.newBufferedWriter(writer1); PrintWriter pw = new PrintWriter(writer2);)  writer1.write("Hello, world. "); pw.printf("\n"); > catch (IOException ex)  System.out.println("Exception: " + ex); > 

Manipulating files on a File System using the Java NIO API

  1. Moving files around It uses the Files factory methods:
    • create: file, directory, symbolic link.
    • delete
    • copy: can copy an input/output stream
    • move
  2. Finding a File in a set of Directories Now supposed that we’re looking for a specific file or a specific set of files, category of files in a given hierarchy of directories, we have thousand of files under directory and we want to find special files among them. We have one pattern for that, a static factory method. From this Files factory class which is called the find() method. The find() method has some parameters:
    • a path which is the root of the directory under which we want to look for information.
    • an integer that is the depth of exploration under this route.
    • an element which is a Predicate, takes a Path under set of attributes. This path represents every elements. This API is going to visit under this hierarchy of directory. So this Path can represent a file or it can represent a directory. The set of attributes will give us information of this path. Is it a file or directory? created date, modification date, owner, the last person modified it, …

For example, find all images in a specific folder.

 Path dir = Paths.get("E:/images"); Path image = Paths.get("image.jpg"); Files.find(dir, 3, (path, attributes) -> path.endsWith(image)); 

For example, find images that have been created between two hours ago and now.

 Path dir = Path.of("E:/images"); Instant twoHoursAgo = Instant.now().minus(Duration.ofHours(2)); Files.find(dir, 3, (path, attributes) ->  attributes.creationTime().toInstant().isAfter(twoHoursAgo); >); 
  • walkFileTree It takes a root directory as a parameter and uses a FileVisitor which is a callback that is going to be called for any elements found in this hierarchy of directory.
  • walk It starts with a path and returns a **Stream ** of all the files and directories. Instead of visiting every element using a callback, it will provide all the elements in a streamer lazily computer so that we don’t lose any kind of performance, and we’re going to process the content of these directory with the map, filter, reduce approach.

Источник

Оцените статью