Image of Java IO: difference between absolute,relative and canonical path

ADVERTISEMENT

Introduction

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.

  1. Access a file using File API

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

File(String pathname)

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

e.g.

File absoluteFile = new File("D:\\sample-documents\\pdf-sample.pdf");
File relativeFile = new File("/sample-documents/pdf-sample.pdf");

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

public class FilePathTest {
 
    public static void main(String[] args) throws IOException {
        accessFileUsingAbsolutePath();
        accessFileUsingRelativePath();
    }
    
    private static void accessFileUsingAbsolutePath()
    {
        System.out.println("Access file using absolute path: ");
        String absolutePath = "D:\\sample-documents\\pdf-sample.pdf";
        File file = new File(absolutePath);
        printPaths(file);
    }
    
    private static void accessFileUsingRelativePath()
    {
        System.out.println("Access file relatively in different ways: ");
        // This goes back to the root drive of the current directory.
        System.out.println("Access file relative to the root drive of the current directory: ");
        File fileRelative = new File("/sample-documents/pdf-sample.pdf");
        printPaths(fileRelative);
 
        // This goes up 2 levels from the current directory
        System.out.println("Access file relative to the current directory: ");
        File fileRelative2 = new File("../../sample-documents/pdf-sample.pdf");
        printPaths(fileRelative2);
 
        System.out.println("Access file relative to the current directory: ");
        File fileRelative3 = new File("../.././sample-documents/pdf-sample.pdf");
        printPaths(fileRelative3);
    }
    
    private static void printPaths(File file)
    {
        try
        {
            System.out.println("File Path = " + file.getPath());
            System.out.println("Absolute Path = " + file.getAbsolutePath());
            System.out.println("Canonical Path = " + file.getCanonicalPath());
            System.out.println("\n");
        }
        catch(Exception ex)
        {
            ex.printStackTrace();
        }
    }
}

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:

Access file using absolute path: 
File Path = D:\sample-documents\pdf-sample.pdf
Absolute Path = D:\sample-documents\pdf-sample.pdf
Canonical Path = D:\sample-documents\pdf-sample.pdf
 
Access file relatively in different ways: 
 
Access file relative to the root drive of the current directory: 
File Path = \sample-documents\pdf-sample.pdf
Absolute Path = D:\sample-documents\pdf-sample.pdf
Canonical Path = D:\sample-documents\pdf-sample.pdf
 
Access file relative to the current directory: 
File Path = ..\..\sample-documents\pdf-sample.pdf
Absolute Path = D:\work-cme\programmer-gate\..\..\sample-documents\pdf-sample.pdf
Canonical Path = D:\sample-documents\pdf-sample.pdf
 
Access file relative to the current directory: 
File Path = ..\..\.\sample-documents\pdf-sample.pdf
Absolute Path = D:\work-cme\programmer-gate\..\..\.\sample-documents\pdf-sample.pdf
Canonical Path = D:\sample-documents\pdf-sample.pdf

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.

Summary

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.

Next Steps

If you're interested in learning more about the basics of Java, coding, and software development, check out our Coding Essentials Guidebook for Developers, where we cover the essential languages, concepts, and tools that you'll need to become a professional developer.

Thanks and happy coding! We hope you enjoyed this article. If you have any questions or comments, feel free to reach out to jacob@initialcommit.io.