Tuesday, November 10, 2015

Break down class "Files" of java 7 NIO.2

Since Java 7, File related IO operation has been redesigned. The following 3 classes/interfaces are key for file related operations: Path,Paths, and Files. They are all in package java.nio.file. Among all these 3, Files is the most fundamental one.

0. Brief about Path and Paths

Paths is a concrete classes which only has method get(...) to create Path instance. so Paths is just a factory class whose only usage is get a Path instance from a input String or URL to static method get(...)

Path is an interface designed to replace old-styled java.io.File class.  First thing to notice is that Path is not a class but a interface, can't create instance with keyword new. So Paths was introduced for doing the initial.  Second thing need to know about Path is its all method will not do all really I/O, just string manipulation. All methods of Path will not touch anything on the HD. For example method to normalize a path "/usr/local/../bin/../tmp" to path "/usr/tmp" located in class Path.

Then who make the "real" I/O operation? The class Files - this beauty has it all! 

1. Anatomy of class Files

Files is a concrete class only has plenty of static methods. All most all methods need Path instance as its first parameter.

java_nio_file

There seems a lot of stuff, but take it easy, let's go through them step by step. The functions can be categorized in 4 groups.  Also The diagram contains most used methods of Files, but not all. The methods' signature are simplified just for easy to understand without bothering too many details.

  • group 1, basic manipulation. Create/Delete/Rename/Move a file or directory on the file system.
  • group 2, go through directory. 2 methods used to list directory contents without and with subdirectories respectively.
  • group 3, read/write content of file.
  • group 4. get/set file related attributes (the rest parts on the above diagram with pink/blue/green colors)

1.1 Basic I/O manipulation

The methods in these group are pretty self-explained.  By utilizing methods in this group you should be able solve followings:

  • How to create/copy/rename/move/delete a single file?
  • How to create/copy/delete empty directory, rename/move non-empty directory?

There is no single method can copy/delete non-empty directory, has to fulfill that with methods in group 2.

1.2 Go through directory

There are 2 methods in this group. Method newDirectoryStream() works just like command-line 'ls' or 'dir', not recursively deep into subdirectories. On the contrary, walkFileTree() recursively go though every subdirectories.

How to list a directory, only one tier?

  public static void listDirectory(String dir) throws IOException {
Path path = Paths.get(dir);
DirectoryStream<Path> dirStream = Files.newDirectoryStream(path, "*.java");

for (Path p:dirStream) {
// do something will every file/subdir in this directory
System.out.println(p.getFileName());
}
}

How to go through a direcoty recursively, include all subdirectories ?

  public static void goThoughDirectoryRecursively(String dir) throws IOException {
Path path = Paths.get(dir);
Files.walkFileTree(path, new SimpleFileVisitor<Path> () {
@Override
public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) throws IOException {
System.out.println(path); // print out name of every file/directory
return FileVisitResult.CONTINUE;
}
});
}

The walkFileTree() usage is a standard incarnation of "Visitor" design pattern.


1.3 Read/write file contents


These group are for reading or writing contents of file. Use Reader/Writer for text file and InputStream/OutputStream for binary file. Also there are helper methods to read all contents at once for small files.

  public static void readSingleFile(String fileName) throws IOException {
Path path = Paths.get(fileName);
BufferedReader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8);

// print the file content to screen
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
reader.close();
}

1.4 Get/set file attributes


The file and directory on file system can have many attributes, some basic attributes like creation/access/modification time. some of the attributes are specific to windows, like is the file hidden? Some of them are specific to Unix, like is the file writable to other users?


There are 3 ways to get/set file attributes:

  • Use simple shortcut static methods provided by class Files to test and set  (pink on the diagram)
  • Use attributes related classes  like XXXFileAttributes and XXXFileAttributeView (blue on the diagram, see explanation below)
  • Use powerful shortcut static methods getAttribute()/setAttribute() (green on the diagram, see blow)

1.4.1 simple shortcut


The methods for simple shortcuts are ....simple. yes, they are strait forward.  But simple shortcuts don't cover all attributes just some most used ones. Also you may already notice that fewer methods for set than get. ( There is a 'hole' on up-right corner). Shortcut methods in fact just use other attributes related classes we will see below for simplicity.


1.4.2 attributes related classes


Check the blue part on the diagram, left 3 named like XXXFileAttributes, which are read-only. Right 3 named like XXXFileAttributeView are used for file attribute modification.  The XXX here in class name is called view-name, we'll see the usage of view-name very soon.


Here is code snippet to read file attributes on windows.

  // test if a file is read-only on Windows
public static boolean isFileReadOnly(String fileName) throws IOException {
Path path = Paths.get(fileName);
DosFileAttributes dosAttr = Files.readAttributes(path, DosFileAttributes.class);
return dosAttr.isReadOnly();
}

Here is code snippet for modify file attributes on Linux

  // set file permission to "rw-r--r--" on Linux
public static void modifyFilePermission(String fileName) throws IOException {
Path path = Paths.get(fileName);
PosixFileAttributeView posixAttrView = Files.getFileAttributeView(path, PosixFileAttributeView.class);
posixAttrView.setPermissions(PosixFilePermissions.fromString("rw-r--r--"));
}

1.4.3 powerful shortcut


Unlike simple shortcuts, powerful shortcuts only have a pair of getAttribute(path,attributeString...)/setAttribute(path,attributeString...) , but can cover all file attributes. The format of string parameter attributeString is  [view-name:]attribute-name

  • The default value for view-name is basic
  • The attribute-name is in lower case.
  • Need type-casting because get/set only return or use Object instance as values 

We have a code snippet above isFileReadOnly(...) to test if a file is read-only on windows. Here is the equivalent.

  // test if a file is read-only on Windows 
public static boolean isFileReadOnly(String fileName) throws IOException {
Path path = Paths.get(fileName);
return (boolean) Files.getAttribute(path, "dos:readonly");
}

2.Recap


Get a clear view of class Files will give you a good understanding of file related I/O functions in Java 7 + NIO.2.  Again let's review these 4 groups :

  • group 1, basic manipulation. Create/Delete/Rename/Move a file or directory on the file system.
  • group 2, go through directory. 2 methods used to list directory contents without and with subdirectories respectively.
  • group 3, read/write content of file.
  • group 4. get/set file related attributes (the rest parts on the above diagram with pink/blue/green colors)

0 comments:

Post a Comment

Powered by Blogger.

About The Author

My Photo

Has been a senior software developer, project manager for 10+ years. Dedicate himself to Alcatel-Lucent and China Telecom for delivering software solutions.

Pages

Unordered List