Java NIO Path
Jakob Jenkov |
The Java Path
interface is part of the Java NIO 2 update which Java NIO received in Java 6 and Java 7.
The Java Path
interface was added to Java NIO in Java 7.
The Path
interface is located in the java.nio.file
package, so the fully qualified
name of the Java Path
interface is java.nio.file.Path
.
A Java Path
instance represents a path in the file system. A path can point to either a file or a directory.
A path can be absolute or relative. An absolute path contains the full path from the root of the file system down to the file or
directory it points to. A relative path contains the path to the file or directory relative to some other path.
Relative paths may sound a bit confusing. Don't worry. I will explain relative paths in more detail later in this
Java NIO Path tutorial.
Do not confuse a file system path with the
path
environment variable in some operating systems. The java.nio.file.Path
interface has
nothing to do with the path
environment variable.
In many ways the java.nio.file.Path
interface is similar to the java.io.File
class, but there are some minor differences. In many cases though, you can replace the use of the File
class
with use of the Path
interface.
Creating a Path Instance
In order to use a java.nio.file.Path
instance you must create a Path
instance. You
create a Path
instance using a static method in the Paths
class (java.nio.file.Paths
)
named Paths.get()
. Here is a Java Paths.get()
example:
import java.nio.file.Path; import java.nio.file.Paths; public class PathExample { public static void main(String[] args) { Path path = Paths.get("c:\\data\\myfile.txt"); } }
Notice the two import
statements at the top of the example. To use the Path
interface
and the Paths
class we must first import them.
Second, notice the Paths.get("c:\\data\\myfile.txt")
method call. It is the call to the Paths.get()
method that creates the Path
instance. The Paths.get()
method is a factory method for
Path
instances, in other words.
Creating an Absolute Path
Creating an absolute path is done by calling the Paths.get()
factory method with the absolute file
as parameter. Here is an example of creating a Path
instance representing an absolute path:
Path path = Paths.get("c:\\data\\myfile.txt");
The absolute path is c:\data\myfile.txt
. The double \
characters are necessary in Java
strings, since the \
is an escape character, meaning the following character tells what character is
really to be located at this place in the string. By writing \\
you tell the Java compiler to write
a single \
character into the string.
The above path is a Windows file system path. On a Unix system (Linux, MacOS, FreeBSD etc.) the above absolute path could look like this:
Path path = Paths.get("/home/jakobjenkov/myfile.txt");
The absolute path is now /home/jakobjenkov/myfile.txt
.
If you used this kind of path on a Windows machine (a path starting with /
) the path would be
interpreted as relative to the current drive. For instance, the path
/home/jakobjenkov/myfile.txt
could be interpreted as being located on the C drive. Then the path would correspond to this full path:
C:/home/jakobjenkov/myfile.txt
Creating a Relative Path
A relative path is a path that points from one path (the base path) to a directory or file. The full path (the absolute path) of a relative path is derived by combining the base path with the relative path.
The Java NIO Path
class can also be used to work with relative paths.
You create a relative path using the Paths.get(basePath, relativePath)
method. Here are two relative
path examples in Java:
Path projects = Paths.get("d:\\data", "projects"); Path file = Paths.get("d:\\data", "projects\\a-project\\myfile.txt");
The first example creates a Java Path
instance which points to the path (directory) d:\data\projects
.
The second example creates a Path
instance which points to the path (file) d:\data\projects\a-project\myfile.txt
.
When working with relative paths there are two special codes you can use inside the path string. These codes are:
- .
- ..
The .
code means "current directory". For instance, if you create a relative path like this:
Path currentDir = Paths.get("."); System.out.println(currentDir.toAbsolutePath());
Then the absolute path the Java Path
instance corresponds to will be the directory in which the
application executing the above code is executed.
If the .
is used in the middle of a path string it just means the same directory as the path
was pointing to at that point. Here is an Path
example illustrating that:
Path currentDir = Paths.get("d:\\data\\projects\.\a-project");
This path will correspond to the path:
d:\data\projects\a-project
The ..
code means "parent directory" or "one directory up". Here is a Path
Java example
illustrating that:
Path parentDir = Paths.get("..");
The Path
instance created by this example would correspond to the parent directory of the directory
from which the application running this code was started.
If you use the ..
code in the middle of a path string it will correspond to changing one directory
up at that point in the path string. For instance:
String path = "d:\\data\\projects\\a-project\\..\\another-project"; Path parentDir2 = Paths.get(path);
The Java Path
instance created by this example will correspond to this absolute path:
d:\data\projects\another-project
The ..
code after the a-project
directory changes directory up the the parent
directory projects
and then the path references down into the another-project
directory
from there.
The .
and ..
codes also work in combination with the two-string Paths.get()
method. Here are two Java Paths.get()
examples showing simple examples of that:
Path path1 = Paths.get("d:\\data\\projects", ".\\a-project"); Path path2 = Paths.get("d:\\data\\projects\\a-project", "..\\another-project");
There are more ways that the Java NIO Path
class can be used to work with relative paths. You will
learn more about that later in this tutorial.
relativize()
The Java Path method relativize()
can create a new Path which represents the second Path relative
to the first Path. For instance, with the path /data
and /data/subdata/subsubdata/myfile.txt"
,
the second path can be expressed as /subdata/subsubdata/myfile.txt
relative to the first path.
Look at the following example:
Path basePath = Paths.get("/data"); Path path = Paths.get("/data/subdata/subsubdata/myfile.txt"); Path basePathToPath = basePath.relativize(path); Path pathToBasePath = path.relativize(basePath); System.out.println(basePathToPath); System.out.println(pathToBasePath);
The output printed from this example will be:
subdata/subsubdata/myfile.txt ../../..
If you add the relative path subdata/subsubdata/myfile.txt
to the directory path /data
, you get
the full path /data/subdata/subsubdata/myfile.txt
.
If you you add the relative path ../../..
to the full file path /data/subdata/subsubdata/myfile.txt
then you get /data
Note: You cannot mix relative and absolute paths when trying to calculate the relative path from one Path to another Path. The relativize() method will fail with an exception. Thus, this is not allowed:
Path basePath = Paths.get("/data"); Path path = Paths.get("myfile.txt"); Path basePathToPath = basePath.relativize(path);
If you try this, you will the following exception:
Exception in thread "main" java.lang.IllegalArgumentException: 'other' is different type of Path at java.base/sun.nio.fs.WindowsPath.relativize(WindowsPath.java:400) at java.base/sun.nio.fs.WindowsPath.relativize(WindowsPath.java:42) at com.jenkov.java.nio.PathExamples.main(PathExamples.java:33)
normalize()
The normalize()
method of the Path
interface can normalize a path. Normalizing means
that it removes all the .
and ..
codes in the middle of the path string, and resolves
what path the path string refers to. Here is a Java Path.normalize()
example:
String originalPath = "d:\\data\\projects\\a-project\\..\\another-project"; Path path1 = Paths.get(originalPath); System.out.println("path1 = " + path1); Path path2 = path1.normalize(); System.out.println("path2 = " + path2);
This Path
example first creates a path string with a ..
code in the middle. Then the example
creates a Path
instance from this path string, and prints that Path
instance out (actually
it prints Path.toString()
).
The example then calls normalize()
on the created Path
instance, which returns a new
Path
instance. This new, normalized Path
instance is then also printed out.
Here is the output printed from the above example:
path1 = d:\data\projects\a-project\..\another-project path2 = d:\data\projects\another-project
As you can see, the normalized path does not contain the a-project\..
part, as this is redundant.
The removed part adds nothing to the final absolute path.
Tweet | |
Jakob Jenkov |