Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 744
Eswar Avatar asked Jan 11 '14 10:01

Eswar


People also ask

How do relative file paths work?

A relative path refers to a location that is relative to a current directory. Relative paths make use of two special symbols, a dot (.) and a double-dot (..), which translate into the current directory and the parent directory. Double dots are used for moving up in the hierarchy.

What does path resolve do in Java?

resolve(String other) method of java. nio. file. Path used to converts a given path string to a Path and resolves it against this Path in the exact same manner as specified by the resolve method.


1 Answers

There is a concept of a working directory.
This directory is represented by a . (dot).
In relative paths, everything else is relative to it.

Simply put the . (the working directory) is where you run your program.
In some cases the working directory can be changed but in general this is
what the dot represents. I think this is C:\JavaForTesters\ in your case.

So test\..\test.txt means: the sub-directory test
in my working directory, then one level up, then the
file test.txt. This is basically the same as just test.txt.

For more details check here.

http://docs.oracle.com/javase/7/docs/api/java/io/File.html

http://docs.oracle.com/javase/tutorial/essential/io/pathOps.html

like image 87
peter.petrov Avatar answered Sep 21 '22 21:09

peter.petrov