Java IO: difference between absolute,relative and canonical path

The common way of accessing the file system in java is through the java.io.File API. In this tutorial, we explain how to use the File API to access a file using absolute and relative paths, we also describe the difference between getPath(), getAbsolutePath() and getCanonicalPath() methods provided by the API.

1. Absolute vs Relative

In general, a path is a way to refer to a particular file or directory in a file system, there are 2 types of path: absolute and relative. One should understand the difference between these 2 types in order to successfully locate a file within a program.

Absolute Path

Simply, a path is absolute if it starts with the root element of the file system. In windows, the root element is a drive e.g. C:\\, D:\\, while in unix it is denoted by “/” character.

An absolute path is complete in that no other information is required to locate the file, it usually holds the complete directory list starting from the root node of the file system till reaching the file or directory it denotes.

Since absolute path is static and platform dependent, it is a bad practice to locate a file using absolute path inside your program, since you will lose the ability to reuse your program on different machines and platforms.

Relative Path

A relative path is a path which doesn’t start with the root element of the file system. It is simply the path needed in order to locate the file from within the current directory of your program. It is not complete and needs to be combined with the current directory path in order to reach the requested file.

In order to construct a rigid and platform independent program, it is a common convention to use a relative path when locating a file inside your program.

2. Access a file using File API

In order to access a file using File API, developers normally use the following constructor:

This constructor accepts a file path as an argument, either relative or absolute.

e.g.

Both objects refer to the same file, absoluteFile uses an absolute path while relativeFile uses a relative path assuming that our application exists on the D drive.

3. How to get the path of an existing file object

In order to get the path of an existing file object, File api provides 3 different methods:

getPath(): This method just returns the path argument which is used when constructing the object. e.g. relativeFile.getPath() => /sample-documents/pdf-sample.pdf

getAbsolutePath(): This method returns the absolute path of the current file object, a single file existing on a system can have many different paths that refer to it. e.g. The absolute paths of pdf-sample.pdf are:

“D:\sample-documents\pdf-sample.pdf”

“D:\sample-documents\.\pdf-sample.pdf”

“D:\sample-documents\..\sample-documents\pdf-sample.pdf”

Normally, this method returns the “.” and “..” characters, so it’s not efficient for comparing 2 file paths.

getCanonicalPath(): A canonical path is simply a unique absolute path e.g. the canonical path of pdf-sample.pdf is:

“D:\sample-documents\pdf-sample.pdf”

Normally, this method resolves the “.” and “..” characters and return the final path, it’s efficient for comparing 2 file paths.

4. Practical example

In the following example, we create a test class FilePathTest.java, which accesses a file called pdf-sample.pdf using absolute and relative paths, and we validate how the values of getPath(), getAbsolutePath() and getCanonicalPath() methods change according to the value of the original path used in the File constructor.

In this example, we assume that our file is located under D:\sample-documents\ directory and we consider that the path of our project is D:\workspace\programmer-gate

The accessFileUsingAbsolutePath() method is straightforward, we just hard-coded the absolute path of the file and access it using File API, this method is not reusable and can’t run on different machines.

Before discussing accessFileUsingRelativePath() method, it is worth to mention that eclipse uses the root directory of the project when constructing a relative path at runtime e.g. (D:\workspace\programmer-gate), however when running the application through an executable jar file, the current directory of the jar is considered. So make sure to keep this in mind when using a relative path in your application.

In accessFileUsingRelativePath(), we access the file relatively in 2 ways:

  1. 1st way (/sample-documents/pdf-sample.pdf): we’re sure that the file exists on D: drive, so we directly go back to the root drive of our directory using “/” character as a prefix, and then we move down till reaching our file.
  2. 2nd way (“../../sample-documents/pdf-sample.pdf”): we go up 2 levels from our current location (D:\workspace\programmer-gate) using “..” character, then we move down till reaching our file.

So in short, when using “/” character as a prefix in a relative path, java constructs the path starting from the root drive of your current directory otherwise it constructs it from your current directory.

Now if we run the above example, we get the following output:

Finally, getPath() always returns the argument of the constructor as it is, regardless if it’s absolute or relative. getAbsolutePath() and getCanonicalPath() both return an absolute path of the file, however it’s recommended to always use the canonical path since it doesn’t contain the special characters “.” and “..”, hence makes it feasible to be used in comparison operations.

 

Hussein Terek

Founder of programmergate.com, I have a passion in software engineering and everything related to java environment.

You may also like...

3
Leave a Reply

avatar
3 Comment threads
0 Thread replies
0 Followers
 
Most reacted comment
Hottest comment thread
3 Comment authors
Saroj SinghNikolajMehmet Emin Recent comment authors
newest oldest most voted
Mehmet Emin
Guest
Mehmet Emin

Thank you, nice explanation.

Nikolaj
Guest
Nikolaj

You say the relative path starts with a “slash”. But if you do that on unix, well you are signing up for trouble.
Relative path should rather be “path/to/file” not “/path/to/file”

Saroj Singh
Guest
Saroj Singh

Good explanation. Thanks!