How is File(".").getAbsolutePath() resolved under the hood? - java

I was wondering:
What happens after I ask for an absolute path of the current file in Java?
String s = File(".").getAbsolutePath();
How does an interpreter find the path to the current file in the filesystem? Is there some OS system call for this?
Does it return the path of a jar? Or sometimes it can return the path where the file was before compilation?

Every process has a "current directory".
From within the process, the path . refers to this current directory.
The actual path denoted by the current directory is (can be) a parameter to the system call that created the process (see ProcessBuilder for instance), or it can be inherited from the process that creates your process.
The current directory is an attribute of the process, and is completely unrelated to the location of the jar file. The two paths may match by coincidence.
There is no requirement that the . path refer to a writable location, or indeed any location in a filesystem. There may not even be a file system. That is, the path . is not required to exist at all.

For . and .. there is the current working directory, System.getProperty("user.dir"), which may be different at point of excecution, like in the IDE and stand-alone. . has nothing to do with the location of the jar,
but in which directory java is started.
So a path "a/./b/../c" will become "a/c". As there are disk operating systems with ... it just might be that a native call is made. Also Windows might want to replace POSIX / with \.
String to File will always be done at run time. However where the application is started, the current working directory or . - that depends, varies in fact.
Never at compile time, even a static File f = new File("./readme.txt"); creates an object when the class is loaded the first time.
Here File is a class for a phyiscal disk file.
A more general class, Path, is superior in that it can also have its path run inside a zip file, or any feasible URI that provides a file system view.
So I will use Path for further explanation. There is a worthwile utilities class Files with Path operations, allowing you to copy some file from inside a zip archive to some location on hard disk.
Path.absoluteFile is the Path version of getting the absolute path (depending on the file system view).
Path toRealPath​(LinkOption... options) with optional options does disk operating native calls (for a File) when symbolic links are wanted to be replaced with the actual physical paths. /a/b.lnk/c could actually be /a/d/e/c. This call is important should you want to detect if a path unwantedly escapes some restricted directory.

Related

Scanner cannot find (correct) file path

I'm programming in Java with IntelliJ and have been trying to use the Scanner class to read the file. Even with the correct path, I still get a "No such file or directory" error. Does anyone have any suggestions?
My working directory is /Users/kevinliu/Desktop/test
Here is a picture of how the project is set-up.
Are you trying to create a swing/console application using maven?
If yes, maven is not able to find the source. You have to add it on the pom file. See here on how to add it on pom file.
if no, do you have rights to access the address of the image file? Some times, folder are protected by the OS.
You can also use YourClassName.class.getResource("input/input1.txt") to locate file/s under the directory that your class was in.
Even with the correct path, I still get a "No such file or directory" error.
The path is NOT correct. That path says look for a directory called "src" in the root directory of your computer. That is almost certainly not where the input file lives.
If you are going to use an absolute pathname for a file within the working directory that you stated, it should look like this:
/Users/kevinliu/Desktop/test/src/input/input1.txt
(You can check what it will actually be using a file browser ... outside of Intellij.)
If you want to use a relative pathname, try this
src/input/input1.txt
Notes:
There is no leading "/" on a relative pathname. A leading "/" means it is an absolute pathname. Absolute pathnames start at the root directory.
A relative path is resolved relative to the >>current<< working directory. That will depend on where and how you run the application ...
For a production application, you would not want to refer to a file in the source tree. The end user typically won't have the source tree.
Consider making the path a command line argument or configuration setting for your application.
Consider making the file a "resource" that is part of the application's JAR file. (You would open it a different way ...)
If you ever get a "No such file or directory" message, that means that the path is not correct in some sense. You might be in the wrong place, you might not have permission on a parent directory, the file may have been removed or renamed, there may be a you, or something else. Either way, that error comes from the operating system and the OS doesn't make mistakes about these things. The mistake will be yours (or the user's).

getCanonicalPath returns a different path between different platforms

One of the lower methods in my code is getting the canonical path to the temp folder using the file.getCanonicalPath() function (File was defined as File file = new File("/tmp")). This works in linux and windows OS's, but on macOS, this function returns the following string - "/private/tmp" even though I have a tmp folder in my home directory and I don't have /private directory.
Any idea where does this "private" directory is coming from and why this method is not directing me to "/tmp" in macOS even though its accessible?
Note: if I create a random, non- existing dir File object (File file = new File("/random")) it will return the canonical path just fine.
A symbolic link, also termed a soft link, is a special kind of file
that points to another file, much like a shortcut in Windows or a
Macintosh alias. Unlike a hard link, a symbolic link does not contain
the data in the target file. It simply points to another entry
somewhere in the file system.
On macOS /tmp is symlinked to /private/tmp. The directory /private does exist and contains tmp inside it.

System can't find path

Trying to practice Java by doing basic functionality like reading input.
I am trying to parse movies-sample.txt found in:
C:\University\BigDataManagement\Data-Mining\hw1\src\main\resources\movies-sample.txt
Trying to reach movies-sample.txt from
C:\University\BigDataManagement\Data-Mining\hw1\src\main\java
\univ\bigdata\course\MoviesReviewsQueryRunner.java
Using the answer found here on how to parse a large file line by line.
File file = new File("../../../../../resources/movies-sample.txt");
I am getting the following error:
The system cannot find the path specified
Given the above two paths, what am I doing incorrect?
If it's a web app then the resources folder is your root element, otherwise it will be the src folder as mentioned in comments.
In your case here as you are writing a standalone Java program and as your file is loacted in the resources folder, you can use CLassLoader to read the file as a stream.
This is how should be your code:
ClassLoader classloader = Thread.currentThread().getContextClassLoader();
InputStream is = classloader.getResourceAsStream("movies-sample.txt");
Then you will be able to read the is stream line by line.
If you run your program directly from command line, then the path must be related to your current directory.
If you run your program from an IDE, then the current directory of the runnin program depends on the IDE and the way it is configured.
You can determine what is the current directory with System.getProperty("user.dir")
Whatever, hard coding a path in an application is always a bad thing because you cannot ensure where the run was launched from. Either:
it is a user resource, then its path must be input in some way (open... in GUIs apps)
it is a resource needed by the app to run correctly and it should be embedded in some way into the app itself (look for Resource Bundle)
it is a kind of optional external resource (config file for example, or path specified in a config file) and its location should be computed in some way.

Why a Java file exists only in its canonical form?

I'm facing a strange behaviour of the JVM. I wanted to change the user directory, i.e. the dir where files are looked up, that normally corresponds to the path where the java command is run.
So I wrote the following code:
System.setProperty("user.dir", "/tmp/");
File f = new File("myfile");
System.out.println(f.exists());
System.out.println(f.getCanonicalFile().exists());
The file /tmp/myfile exists and is readable by the JVM, but if I'm not in /tmp/ when I run that code, the result is:
false
true
They are the same file, Java is able to retrieve the correct canonical form of it, but the relative one does not exist, while the canonical one exists.
Is it a bug? Is there a way to reliably change the JVM user directory?
Changing the code is not an option, as I'm trying to run external libraries.
This behavior is normal, the reason is, there is a difference between
File f = new File("myfile");
and
File cf = new File("myfile").getCanonicalFile();
The first denotes a filepath relative to your current WORKING DIR, which could be your project path. Using the relative path, the user.dir property is NOT USED, even when setting user.dir as JVM parameter -Duser.dir=/tmp/. The resolution of Java file handles to native file entities is done natively by the underlying Fileystem implementation.
But when invoking getCanoncialFile() before resolving the native file handle the relative path is resolved using the user path information - in your case user.dir = /tmp/.
Apparently, there is no file myfile in <WORKING_DIR> but in /tmp/.
The behavior is the same for f.getAbsoluteFile().

get a file path

Is there a way to get the full path for a file exists on the computer ?
For example , I want to get the full path for a file in a folder on desktop
I tried using :
File f = new File("help.chm");
String f2=f.getAbsolutePath();
f3=f3.replaceAll("\\\\","/" );
System.out.println("Path:"+f3);
but it gave me the path of the project like this:
C:/Users/toshiba/Documents/NetBeansProjects/test/help.chm
although the file is not located there .
If you create a file using new File("filename") which is the relative path, you cannot get the absolute path of the file using file.getAbsolutePath(), because the relative path is build according to the default user home directory or the JVM path.
Take a look at Java Doc: -
A pathname, whether abstract or in string form, may be either absolute
or relative. An absolute pathname is complete in that no other
information is required in order to locate the file that it denotes.
A relative pathname, in contrast, must be interpreted in terms of
information taken from some other pathname. By default the classes in
the java.io package always resolve relative pathnames against the
current user directory. This directory is named by the system property
user.dir, and is typically the directory in which the Java virtual
machine was invoked.
So, to get the absolute path for this case, you would actually have to write the path yourself. Get the absolute path till the directory where you saved the file, and append the file name to it.
Since the other answers do not cover your question, here is my comment:
To get a file's path, you first need to tell your java program where it is or how to find it.
For your specific example you can get the desktop path using: System.getProperty("user.home") + "/Desktop"; then you can search through folders on your desktop for a matching file name.
Read here to learn how to search for files: docs.oracle.com/javase/tutorial/essential/io/find.html
A File is a representation of a file path, not necessarily an existent file on disk - ie the file doesn't have to exist on disk for a File object to be not null.
That's why there's the File.exists() method.
The path "help.chm" will be relative to the directory from which you started the JVM, which in your case appears to be C:/Users/toshiba/Documents/NetBeansProjects/test/
To get a path to the desktop, you need to use the absolute path of the desktop directory in Windows, which will be something along the lines of C:/Users/toshiba/Desktop/help.chm
You are attempting to read the file from (default folder)
C:/Users/toshiba/Documents/NetBeansProjects/test/
File doesn't exist but the would-be-file's path will be
C:/Users/toshiba/Documents/NetBeansProjects/test/
If you read the file from where it really is:
File f = new File("C:/Users/toshiba/Desktop/help.chm");
You will see that exists() returns true.
System.out.println(f.exists());
Then:
String f2=f.getCanonicalPath();

Categories

Resources