Rewrite the code for java.io.File with java.nio.Path and java.nio.Files

Overview

The other day, the code that was using java.io.File with Path and Files Since I replaced it, I will introduce it from the perspective of rewriting the existing code. If you're already familiar with NIO2, you probably won't notice anything after reading this article.

By the way, the new file-related API from JDK7 is called NIO2 (New I / O 2), and the unmarked one seems to refer to the Channel and Charset added in the 1.4 era.

background

The File class has the following two functions.

--Define the location of the file --Manipulate files

It seems that NIO2 of JDK7 divided it as follows.

--Define the location of the file ... java.nio.file.Path Interface --Manipulate files ... java.nio.file.Files

I don't know if the File class will completely replace Path & Files in the future. Looking at the Javadoc for the File class, it seems that toPath () was the only method added in 1.7, and there were no new methods in 1.8, so future file-related API development will be in Files and Path. I don't think it's going to shift. However, there are still quite a few libraries in the JDK that only deal with Files, not Path. As an example, JavaFX FileChooser and Drag & Drop API can only handle File. If you want to work with the Files class, you need to convert it to a Path object with the ToPath () method of the File class.

If you have code running in java.io.File right now and your test code is perfect, you shouldn't force yourself to rewrite it to Path, given the history of Java backwards compatibility. This is also the case if you have to develop in an environment prior to JDK 6 due to circumstances. However, since many of the functions of the Files class are simply excellent, I think that it is an option to try writing in NIO2 for the part to be newly developed, for example.

Caution

NIO2 has been added since JDK7. Unfortunately, most of the classes in the java.nio package are not implemented in the Android SDK, which is said to have roughly the JDK7 libraries.

https://developer.android.com/reference/java/nio/package-summary.html

See the article below for details.

-How much is Android 7?

What not to write in this article

There are many other excellent articles about the library that has been around for more than 5 years, and it is out of the scope of detailed usage of Path and Files, and replacement from File, so I will omit it in this article. To do.


Object creation

For File

I think that File is mainly generated by passing the file path to the constructor as a string (or as a URL).

File file = new File("dir/file.txt");

For Path

There is a factory called Paths and it's ``` get ()` `` Create an object by passing a string or URI as a method argument.

Path path = Paths.get("dir/file.txt");

Mutual conversion between File and Path

File and Path can be converted to each other. If you want to use NIO in a library that doesn't return a Path, like FileChooser above, you can use this method to convert it to a Path object.

File -> Path

Path path = file.toPath();

Path -> File

File file = path.toFile();

Get the absolute path of the file

For File

Use getAbsolutePath, which returns a string of absolute paths.

file.getAbsolutePath();

For NIO2

Use toAbsolutePath to convert it to an absolute path Path object, then toString () to convert it to a string.

path.toAbsolutePath().toString(),

Check the existence of the file

For File

file.exists();

For NIO2

Files.exists(path);

Determine if the file is readable

For File

File.Use canRead.



```java
file.canRead())

For NIO2

files#isreadableIs used.

Files.isReadable(Path)

Create a folder

For File

File.You can also use mkdirs to create a parent folder as well. The success or failure is returned as a boolean.



```java
new File("dir").mkdirs();

For NIO2

Use Files # createDirectories. This method can throw an IOException, so you need to handle the exception.

Files.createDirectories(dirPath);

Determine if it is a folder

It doesn't change that much.

For File

file.isDirectory()

For NIO2

Files.isDirectory(path)

Move files

For File

File.Use renameTo. The success or failure is returned as boolean.



```java
file.renameTo(dest);

For NIO2

files#moveIs used. The path of the modified file is returned.

Files.move(path, destPath);

Delete file

For File

new File("file.txt").delete();

For NIO2

Files.delete(Paths.get("file.txt"));

There is also a method called deleteIfExists that deletes the file when it exists, which returns a boolean value.

Files.deleteIfExists(Paths.get("file.txt"));

Manipulate all files in a folder

Actually, this is strangely difficult.

For java.io.File

For example, if you want to work with all the files in the folder `` `dir```, you could write the code to get the objects as an array in java.io.File as follows.

File[] files = new File("dir").listFiles();

For NIO2

With JDK8, it's easy with `Files # list (Path)`.

Stream<Path> files = Files.list(Paths.get(articleDir));

If you want a List instead of a Stream, collect it.

List<Path> files = Files.list(f).collect(Collectors.toList());

For JDK7, would you use Files.newDirectoryStream ...?

try (final DirectoryStream<Path> directoryStream
                = Files.newDirectoryStream(dir, Articles::isValidContentPath)){
    // ……
} catch (final IOException e) {
    e.printStackTrace();
}

Get the last modified date and time of a file in milliseconds

For File

lastmodified()You can get the milliseconds in the method.

final long lastModifiedMs = file.lastModified();

For NIO2

Files.with getLastModifiedTime[FileTime](https://docs.oracle.com/javase/jp/8/docs/api/java/nio/file/attribute/FileTime.html)Youcangettheobject,sotoMillis()Then, you can get the last update date and time in milliseconds as before. The FileTime class has a variety of different conversion methods that make it easier to avoid some Java in the coding phase: "I intended to get in seconds, but in milliseconds."



```java
Files.getLastModifiedTime(path).toMillis());

However, unlike File # lastModified, getLastModifiedTime can raise an IOException, so you need to handle the exception.


A little handy method for Files

I will introduce some of them.

Files#newBufferedReader(Path path) In the past, it was necessary to wrap the Reader and initialize it as shown below, and I think that I created a method that initializes and returns the FileReader with Oreole FileUtils, or used Apache Commons.

new BufferedReader(new InputStreamReader(new FileInputStream(pTargetFileName), pEncode));

In the case of Files & Path, if the encoding of the file to be read is UTF-8, the following is fine.

final BufferedReader fileReader = Files.newBufferedReader(path)

You can also handle files with different encodings by passing Charset as the second argument.

Files#newBufferedWriter Of course, there are also Writer methods.

final BufferedWriter writer = Files.newBufferedWriter(path);

Files#readAllLines You can read the contents of the file and get what you put in the List line by line. I am grateful that I made this kind of method myself and reused it. IOException exception handling is required.

final List<String> lines = Files.readAllLines(path);

Files#readAllBytes This method is used when you want to read a small file with one byte array.

final byte[] bytes = Files.readAllBytes(path);

Files#write Writes the contents of byte [] to the file with the specified Path. To output the contents of the string str to a file of path, follow the steps below. IOException exception handling is required.

Files.write(path, str.getBytes(StandardCharsets.UTF_8.name()));

Summary

We've focused on how to replace existing File code with Path and Files code. Files have many methods that require exception handling, and you need a programming style that handles exceptions properly. The number of characters to type also tends to increase simply compared to when using File, so it may be difficult to get to the point at first. Unfortunately, methods that require exception handling don't work very well with Lambda expressions.

Also, although I didn't write this time, most of the methods of the Files class assume that the encoding of the file to be handled is UTF-8, so if you are using any other encoding, you will have to deal with it difficult. May be done.


reference

Books

-"Introduction to [Latest] Java SE 7/8 haste that can be used in the field" …… History and background of NIO The significance and usage are introduced in great detail.

Web -File / Directory Operation 2 -Reference memo / Convenient function of file operation of nio2 of Java7 (basename, dirname, realpath equivalent and simple reading and writing of files) -Note on how to recursively process folders with NIO

Recommended Posts

Rewrite the code for java.io.File with java.nio.Path and java.nio.Files
Prepare the environment for java11 and javaFx with Ubuntu 18.4
Code for solving the random number matrix with Pivot Gaussian elimination and Gaussian elimination and comparing the accuracy
Oracle Live for the Code
Sample code for basic mocking and testing with Mockito 3 + JUnit 5
Writing code with classes and instances
Pre-written source code for the activity
Wait for PostgreSQL to start with Docker and then start the WEB service
Source code for finding an orthonormal basis with the Gram-Schmidt orthogonalization method
Link Java and C ++ code with SWIG
Code for solving a random number matrix with the Pivot Gauss elimination method
[Java] Rewrite the functions created by myself in the past from java.io.File with NIO.2.
Experience .NET 5 with Docker and Visual Studio Code
Articles and books useful for studying test code
Specify the timeout for each path with Rack :: Timeout
[Ruby] Setting values ​​and memorandum for the table