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

Solution 1:

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

Solution 2:

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.

Solution 3:

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.

Solution 4:

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.