io

Java 7 New IO API Example

1. Introduction

Java NIO (New IO) is an alternative IO API for Java (from Java 1.4) – it was deemed to be the alternative standard to the Java IO and Java Networking API. Of course, there wouldn’t be a new one if it’s not for the benefits of using it. It does still has the basic file manipulation capabilities but the design team decided to provide an alternative fresh approach to manage the file system. There are two base file manipulation API. One resides on the package java.nio.file with two sub-packages of java.nio.file.attribute and java.nio.fle.spi. The new API separates file related operations from the java.io.package and also provides additional methods to make the management of file systems, more straight forward.

In concept, the new API is built as a set of entity interfaces covering base objects of a file system (which Java is known for – Object oriented). This concept was inherited from the java.util package where classes Collections and Array provide many operations on basic aggregation data structures as a collection and array respectively. It was named differently to clearly state the base classes and interfaces – this will ultimately be apparent when java.io and java.nio.file packages are used together.

2. New Features not found in java.io

The new IO file provides OS specific capabilities that aren’t supported by the older package. One important example is working with links and symbolic links which can now be created and/or processed in any file system traversal operation.

2.1 Symbolic Link

Of course, not all systems support this, in such, a UnsupportedOperationException will be thrown. Another feature is the file attribute management. This is setting owners and permissions. Same as symbolic links, this is not supported by all systems and in such, will throw an UnsupportedOperationException.

Below are the methods that are related to managing links from the Files class.

  • createLink – creates a hard link mapped to a  file
  • createSymbolicLink – creates a symbolic link to a file or directory.
  • getFileAttributesView – access the file attributes in a form of a file system specific implementation (FileAttributeView).
  • getOwner – retrieves the owner of the file.
  • getPosixFilePermissions – gets the file permissions.
  • isSymbolicLink – check if the file indicated is a symbolic link.
  • readSymbolicLink – reads the target path of a symbolic link.
  • readAttributes – gets/reads the file attributes.
  • setAttributes – sets the file attributes.

A full documentation is available here:

ExampleSymbolicLink.java

Path newLink = ...;
Path target = ...;
try {
    Files.createSymbolicLink(newLink, target);
} catch (IOException x) {
    System.err.println(x);
} catch (UnsupportedOperationException x) {
    // Some file systems do not support symbolic links.
    System.err.println(x);
}

2.2 Watches

The API has functions that enables developers to write code that can watch a specific file or directory. Watch meaning, it can hook events of creation, modification or deletion. One down side of this is that this service is system dependent, so we really can’t rely on this function if we are to aim portability.  There are 5 interfaces covering watching functionality.

  • Watchable – This is used to tag a specific class if it can be registered to the watch service or not.
  • WatchService –  The service is available int he file system to register a Watchable object which can be monitored using the WatchKey.
  • WatchKey – The unique identifier of a Watchable object.
  • WatchEvent – The actual event being triggers from the WatchService.
  • WatchEvent.Kind – Carries the kind (type) of information an event has.

DirectoryWatchDemo.java

package net.codejava.io;

import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE;
import static java.nio.file.StandardWatchEventKinds.ENTRY_DELETE;
import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY;

import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;

/**
 * This program demonstrates how to use the Watch Service API to monitor change
 * events for a specific directory.
 * @author www.codejava.net
 *
 */
public class DirectoryWatchDemo {

	public static void main(String[] args) {
		try {
			WatchService watcher = FileSystems.getDefault().newWatchService();
			Path dir = Paths.get("E:/Test/Download");
			dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
			
			System.out.println("Watch Service registered for dir: " + dir.getFileName());
			
			while (true) {
				WatchKey key;
				try {
					key = watcher.take();
				} catch (InterruptedException ex) {
					return;
				}
				
				for (WatchEvent event : key.pollEvents()) {
					WatchEvent.Kind kind = event.kind();
					
					@SuppressWarnings("unchecked")
					WatchEvent ev = (WatchEvent) event;
					Path fileName = ev.context();
					
					System.out.println(kind.name() + ": " + fileName);
					
					if (kind == ENTRY_MODIFY && 
							fileName.toString().equals("DirectoryWatchDemo.java")) {
						System.out.println("My source file has changed!!!");
					}
				}
				
				boolean valid = key.reset();
				if (!valid) {
					break;
				}
			}
			
		} catch (IOException ex) {
			System.err.println(ex);
		}
	}
}

2.3 Utility Operations

The utility methods should be a heavy favorite for all those coders. The new API has a set of utilities that makes the developing with it a breeze. It make the package self-sufficient for the majority of the use cases.

InputStreams, OutputStreams and Byte channels can be obtained directly using the methods under Files class. Complete file manipulation operations such as copying or moving files are supported and in addition, the entire file content can be read now as a list of Strings (line by line) or array of bytes.

CopyFilesExample.java

public class CopyFilesExample {

	public static void main(String[] args) throws InterruptedException,
			IOException {

		File source = new File("\Users\alvinreyes\sourcefile1.txt");
		File dest = new File("\Users\alvinreyes\destinationfile1.txt");

		// copy file using FileStreams
		long start = System.nanoTime();
		long end;
		copyFileUsingFileStreams(source, dest);
		System.out.println("Time taken by FileStreams Copy = "
				+ (System.nanoTime() - start));

		// copy files using java.nio.FileChannel
		source = new File("\Users\alvinreyes\sourcefile2.txt");
		dest = new File("\Users\alvinreyes\destinationfile2.txt");
		start = System.nanoTime();
		copyFileUsingFileChannels(source, dest);
		end = System.nanoTime();
		System.out.println("Time taken by FileChannels Copy = " + (end - start));

		// copy file using Java 7 Files class
		source = new File("\Users\alvinreyes\sourcefile3.txt");
		dest = new File("\Users\alvinreyes\destinationfile3.txt");
		start = System.nanoTime();
		copyFileUsingJava7Files(source, dest);
		end = System.nanoTime();
		System.out.println("Time taken by Java7 Files Copy = " + (end - start));


	}

	private static void copyFileUsingFileStreams(File source, File dest)
			throws IOException {
		InputStream input = null;
		OutputStream output = null;
		try {
			input = new FileInputStream(source);
			output = new FileOutputStream(dest);
			byte[] buf = new byte[1024];
			int bytesRead;
			while ((bytesRead = input.read(buf)) > 0) {
				output.write(buf, 0, bytesRead);
			}
		} finally {
			input.close();
			output.close();
		}
	}

	private static void copyFileUsingFileChannels(File source, File dest)
			throws IOException {
		FileChannel inputChannel = null;
		FileChannel outputChannel = null;
		try {
			inputChannel = new FileInputStream(source).getChannel();
			outputChannel = new FileOutputStream(dest).getChannel();
			outputChannel.transferFrom(inputChannel, 0, inputChannel.size());
		} finally {
			inputChannel.close();
			outputChannel.close();
		}
	}

	private static void copyFileUsingJava7Files(File source, File dest)
			throws IOException {
		Files.copy(source.toPath(), dest.toPath());
	}


}

There’s a lot more to learn and check to the Java 7 new IO API. For me, the take aways are the ones above, with such features, its no question that it’s more capable than the prior standard Java IO package.

2.4 IO File Organization

The file system and storage are an essential part of the new IO file package. A key element to this is the a file location is represented by the Path Interface. You need to get a concrete implementation of that interface using the FileSystem factory, which in turn has to be obtained from the FileSystems factory.

1.0 Relationships between elements of the new IO file.
1.0 Relationships between elements of the new IO file.

3. Do we need to migrate?

I see four reasons to consider migrating to the new File I/O

  • Problems with current one. If we can improve your file system, then its a reason. The new API is backward compatible and would surely benefit the application longevity.
  • You need to support file operations in ZIP archives
  • You need control over file attributes in POSIX systems
  • Watch services

Overall, it really depends on your project. The key take away here is that this is ultimately better than the standard io. It has more wrappers and features that can be used to better manage files and directories. It’s easier to implement and backward compatible with the prior versions.

4. Download the Eclipse project of this tutorial:

This was an example of java 7 new IO API.

Download
You can download the full source code of this example here : java7-new-io.zip

Alvin Reyes

Alvin has an Information Technology Degree from Mapua Institute of Technology. During his studies, he was already heavily involved in a number of small to large projects where he primarily contributes by doing programming, analysis design. After graduating, he continued to do side projects on Mobile, Desktop and Web Applications.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button