[java] How does Java resolve a relative path in new File()?

I am trying to understand the way Java resolves relative path in while creating a File object.

OS used: Windows

For the below snippet, I am getting an IOException as it cannot find the path:

@Test
public void testPathConversion() {
        File f = new File("test/test.txt");
        try {
            f.createNewFile();
            System.out.println(f.getPath());
            System.out.println(f.getAbsolutePath());    
            System.out.println(f.getCanonicalPath());
        } catch (Exception e) {
            e.printStackTrace();
        }
}

My understanding here is, Java treats the path provided as absolute and returns an error when the path does not exist. So it makes sense.

When I update the above code to use relative path:

@Test
    public void testPathConversion() {
        File f = new File("test/../test.txt");
        try {
            f.createNewFile();
            System.out.println(f.getPath());
            System.out.println(f.getAbsolutePath());    
            System.out.println(f.getCanonicalPath());
        } catch (Exception e) {
            e.printStackTrace();
        }    
    }

It creates a new file and provides the below output:

test\..\test.txt
C:\JavaForTesters\test\..\test.txt
C:\JavaForTesters\test.txt

In this case, my assumption is, even though the path provided doesn't exist, because the path contains "/../", java treats this as a relative path and creates the file in the user.dir. So this also makes sense.

But if I update the relative path as below:

   @Test
    public void testPathConversion() {
        File f = new File("test/../../test.txt");
        try {
            f.createNewFile();
            System.out.println(f.getPath());
            System.out.println(f.getAbsolutePath());
            System.out.println(f.getCanonicalPath());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

Then I get IOException: Access is denied.

My questions are:

  1. why "test/../test.txt" is treated as a relative path and creates the file in "user.dir" but"test/../../test.txt" returns an error? Where does it attempt to create the file for the path "test/../../test.txt"?
  2. When the specified relative path is not found, the file seems to be created in the user.dir. So, it appears to me that the below two scenarios does the same thing:

    //scenario 1
    File f = new File("test/../test.txt");
    f.createNewFile();
    
    //scenario 2
    File f = new File("test.txt");
    f.createNewFile();
    

So is there a real world case where one would use scenario 1 instead of scenario 2?

I suppose I am missing something obvious here or have fundamentally misunderstood relative paths. I went through the Java docs for File and I am not able to find an explanation for this. There are quite a few questions posted in Stack Overflow regarding relative paths, but the ones I looked up were for specific scenarios and not exactly about how relative paths are resolved.

It will be great if someone could please explain me how this works or point to some related links?

This question is related to java file relative-path

The answer is


On windows and Netbeans you can set the relative path as:

    new FileReader("src\\PACKAGE_NAME\\FILENAME");

On Linux and Netbeans you can set the relative path as:

    new FileReader("src/PACKAGE_NAME/FILENAME");

If you have your code inside Source Packages I do not know if it is the same for eclipse or other IDE


The working directory is a common concept across virtually all operating systems and program languages etc. It's the directory in which your program is running. This is usually (but not always, there are ways to change it) the directory the application is in.

Relative paths are ones that start without a drive specifier. So in linux they don't start with a /, in windows they don't start with a C:\, etc. These always start from your working directory.

Absolute paths are the ones that start with a drive (or machine for network paths) specifier. They always go from the start of that drive.


Only slightly related to the question, but try to wrap your head around this one. So un-intuitive:

import java.nio.file.*;
class Main {
  public static void main(String[] args) {
    Path p1 = Paths.get("/personal/./photos/./readme.txt");
    Path p2 = Paths.get("/personal/index.html");
    Path p3 = p1.relativize(p2);
    System.out.println(p3); //prints  ../../../../index.html  !!
  }
}

When your path starts with a root dir i.e. C:\ in windows or / in Unix or in java resources path, it is considered to be an absolute path. Everything else is relative, so

new File("test.txt") is the same as new File("./test.txt")

new File("test/../test.txt") is the same as new File("./test/../test.txt")

The major difference between getAbsolutePath and getCanonicalPath is that the first one concatenates a parent and a child path, so it may contain dots: .. or .. getCanonicalPath will always return the same path for a particular file.

Note: File.equals uses an abstract form of a path (getAbsolutePath) to compare files, so this means that two File objects for the same might not be equal and Files are unsafe to use in collections like Map or Set.


Relative paths can be best understood if you know how Java runs the program.

There is a concept of working directory when running programs in Java. Assuming you have a class, say, FileHelper that does the IO under /User/home/Desktop/projectRoot/src/topLevelPackage/.

Depending on the case where you invoke java to run the program, you will have different working directory. If you run your program from within and IDE, it will most probably be projectRoot.

  • In this case $ projectRoot/src : java topLevelPackage.FileHelper it will be src.

  • In this case $ projectRoot : java -cp src topLevelPackage.FileHelper it will be projectRoot.

  • In this case $ /User/home/Desktop : java -cp ./projectRoot/src topLevelPackage.FileHelper it will be Desktop.

(Assuming $ is your command prompt with standard Unix-like FileSystem. Similar correspondence/parallels with Windows system)

So, your relative path root (.) resolves to your working directory. Thus to be better sure of where to write files, it's said to consider below approach.

package topLevelPackage

import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;

public class FileHelper {

    // Not full implementation, just barebone stub for path
    public void createLocalFile() {

        // Explicitly get hold of working directory
        String workingDir = System.getProperty("user.dir");

        Path filePath = Paths.get(workingDir+File.separator+"sampleFile.txt");

        // In case we need specific path, traverse that path, rather using . or .. 
        Path pathToProjectRoot = Paths.get(System.getProperty("user.home"), "Desktop", "projectRoot");

        System.out.println(filePath);
        System.out.println(pathToProjectRoot);

    }
}

Hope this helps.


I went off of peter.petrov's answer but let me explain where you make the file edits to change it to a relative path.

Simply edit "AXLAPIService.java" and change

url = new URL("file:C:users..../schema/current/AXLAPI.wsdl");

to

url = new URL("file:./schema/current/AXLAPI.wsdl");

or where ever you want to store it.

You can still work on packaging the wsdl file into the meta-inf folder in the jar but this was the simplest way to get it working for me.


Examples related to java

Under what circumstances can I call findViewById with an Options Menu / Action Bar item? How much should a function trust another function How to implement a simple scenario the OO way Two constructors How do I get some variable from another class in Java? this in equals method How to split a string in two and store it in a field How to do perspective fixing? String index out of range: 4 My eclipse won't open, i download the bundle pack it keeps saying error log

Examples related to file

Gradle - Move a folder from ABC to XYZ Difference between opening a file in binary vs text Angular: How to download a file from HttpClient? Python error message io.UnsupportedOperation: not readable java.io.FileNotFoundException: class path resource cannot be opened because it does not exist Writing JSON object to a JSON file with fs.writeFileSync How to read/write files in .Net Core? How to write to a CSV line by line? Writing a dictionary to a text file? What are the pros and cons of parquet format compared to other formats?

Examples related to relative-path

webpack: Module not found: Error: Can't resolve (with relative path) Reading file using relative path in python project How to import a CSS file in a React Component How to open my files in data_folder with pandas using relative path? Relative path in HTML Failed to load resource: the server responded with a status of 404 (Not Found) How does Java resolve a relative path in new File()? relative path in BAT script How to define a relative path in java Relative imports for the billionth time