I set java property user.dir to /home/alex/projects/poltava/rpgu/workingdir. Also I have file q.txt inside above folder.
Below is the code snippets and their return values (after =):
System.getProperty("user.dir") = /home/alex/projects/poltava/rpgu/workingdir
new File(".").getAbsolutePath() = /home/alex/projects/poltava/rpgu/workingdir/.
new File(".").exists() = true
new File("q.txt").getAbsolutePath() = /home/alex/projects/poltava/rpgu/workingdir/q.txt
new File("q.txt").exists() = false
new File(new File("q.txt").getAbsolutePath()).exists() = true
new FileInputStream("q.txt") = threw FileNotFoundException
So that as you can see file is realy exists in file system. When I try to get it with absolute path, everything is well. When I try to get it with relative path, it fails.
What do I wrong with relative path?
EDITED:
Small application that demonstrates the problem:
import java.io.File;
public class Test {
public static void main(String[] args) {
System.setProperty("user.dir", "/home/alex/projects/poltava/rpgu/workingdir");
System.out.println(System.getProperty("user.dir"));
System.out.println(new File("q.txt").exists());
System.out.println(new File("q.txt").isFile());
System.out.println(new File("q.txt").canRead());
System.out.println(new File("q.txt").getAbsolutePath());
System.out.println(new File(new File("q.txt").getAbsolutePath()).exists());
System.out.println(new File(new File("q.txt").getAbsolutePath()).isFile());
System.out.println(new File(new File("q.txt").getAbsolutePath()).canRead());
try {
new FileInputStream("q.txt");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
Output:
/home/alex/projects/poltava/rpgu/workingdir
false
false
false
/home/alex/projects/poltava/rpgu/workingdir/q.txt
true
true
true
java.io.FileNotFoundException: q.txt (No such file or directory)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.<init>(FileInputStream.java:146)
at java.io.FileInputStream.<init>(FileInputStream.java:101)
at Test.main(Test.java:24)
EDITED 2:
I also tried another simple example:
File f = new File("q1.txt");
System.out.println(f.createNewFile());
System.out.println(f.getPath());
System.out.println(f.getAbsolutePath());
An output:
true
q1.txt
/home/alex/projects/poltava/rpgu/workingdir/q1.txt
In result file is created in directory from which I launch the application. Not in user.dir directory. And getAbsolutePath() returns incorrect file path.
I think it would serve you better to read the javadoc for File.
A little bit of explanation to help you get started:
For the constructor that you're using:
public File(String pathname)
Creates a new File instance by converting the given pathname string
into an abstract pathname. If the given string is the empty string,
then the result is the empty abstract pathname.
So essentially what you get is a File instance, with the abstract pathname "q.txt".
What happens when you do a getAbsolutePath() on this. Again from the javadoc:
public String getAbsolutePath()
Returns the absolute pathname string of this abstract pathname.
If this abstract pathname is already absolute, then the pathname
string is simply returned as if by the getPath() method. If this
abstract pathname is the empty abstract pathname then the pathname
string of the current user directory, which is named by the system
property user.dir, is returned. Otherwise this pathname is resolved in
a system-dependent way. On UNIX systems, a relative pathname is made
absolute by resolving it against the current user directory.
On Microsoft Windows systems, a relative pathname is made absolute
by resolving it against the current directory of the drive named by
the pathname, if any; if not, it is resolved against the current
user directory.
Do you see what is happening? Especially, with respect to user.dir?
More hints:
Now create another variable, e.g.
File newFile = new File(System.getProperty("user.dir"), "q.txt").
Try the same operations on newFile. Try using getParent() on your previous one as well as on this one. You'll see the difference.
I hope this helps clarify a few points for you :)
It is because File(String str) will call normalize, but getAbsolutePath will also call resolve, there is where the user.dir is being used. Look at the following example.
System.setProperty("user.dir", "/home/alex/projects/poltava/rpgu/workingdir");
File fString = new File("Test.txt");
File fAbsolutePath = new File(fString.getAbsolutePath());
System.out.println(System.getProperty("user.dir"));
System.out.println(fString.getPath());
System.out.println(fAbsolutePath.getPath());
Here is the output:
/home/alex/projects/poltava/rpgu/workingdir
Test.txt
\home\alex\projects\poltava\rpgu\workingdir\Test.txt
You can see the src code here:
new File(String str)
http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7-b147/java/io/File.java#File.%3Cinit%3E%28java.io.File%2Cjava.lang.String%29
getAbsolutePath:
http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7-b147/java/io/File.java#File.getAbsolutePath%28%29
Related
I have a simple line of code that should print out first line of a file:
System.out.println(new BufferedReader(new FileReader("file")).readLine());
The class file with this line is located in c:/users/my/project.
A file named "file" exists in c:/users/my/project.
If I open CMD, navigate to c:/users/my/project and run
java MyClass
The first line is printed out and everything is fine.
But if I navigate to C:/ in CMD, and run
java -Duser.dir=c:/users/my/project MyClass
I get a response that file "file" could not be found.
If I move "file" to c:/ and run the same command again then it is found.
As I understand it, changing the user.dir should be equivalent to me being in the folder that it points to but that doesent seem to be true. The class file is found in user.dir, but files are still found in the folder I ran the command in, not the folder that user.dir points to.
Why is this?
If you navigate to another directory and try to run your program with a different user.dir, you also have to set the classpath. The error you get is because it can't find the class, not because it can't find the file.
Try
java -Duser.dir=c:/users/my/project -classpath c:/users/my/project MyClass
Regarding the user.dir property, have a look at the documentation for the File class. It states
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.
EDIT
I did a test on my machine and found that file reader looks in the directory that the application was launched from (which may not coincide with the user.dir property). See below:
public static void main(String...args) {
try {
System.out.println("abs path to test.txt : " + new java.io.File("test.txt").getAbsolutePath());
System.out.println("user home : " + System.getProperty("user.home"));
System.out.println("user.dir : " + System.getProperty("user.dir"));
System.out.println("running from : " + new java.io.File(".").getAbsolutePath());
System.out.println(new java.io.BufferedReader(new java.io.FileReader("test.txt")).readLine());
} catch (Exception e) {
System.out.println("Not found");
}
}
Launching this from a directory that doesn't have the file in it I get
C:\Users>java -Duser.home=C:\Users\william -Duser.dir=C:\Users\william -classpath C:\Users\william\Desktop Test
abs path to test.txt : C:\Users\william\test.txt
user home : C:\Users\william
user.dir : C:\Users\william
running from : C:\Users\william\.
Not found
Whereas launching it from a directory that has the file I'm looking for I get
C:\Users\william>java -Duser.home=C:\Users\william -Duser.dir=C:\Users\william -classpath C:\Users\william\Desktop Test
abs path to test.txt : C:\Users\william\test.txt
user home : C:\Users\william
user.dir : C:\Users\william
running from : C:\Users\william\.
hello world
ANOTHER EDIT
I'm using the openjdk 8, so in my case the logic is as follows, from its source:
FileReader constructor with String arg
public FileReader(String fileName) throws FileNotFoundException {
super(new FileInputStream(fileName));
}
FileInputStream constructors
public FileInputStream(String name) throws FileNotFoundException {
this(name != null ? new File(name) : null);
}
public FileInputStream(File file) throws FileNotFoundException {
String name = (file != null ? file.getPath() : null);
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkRead(name);
}
if (name == null) {
throw new NullPointerException();
}
if (file.isInvalid()) {
throw new FileNotFoundException("Invalid file path");
}
fd = new FileDescriptor();
fd.attach(this);
path = name;
open(name);
}
FileInputStream open(String)
private void open(String name) throws FileNotFoundException {
open0(name);
}
The open0(String) method is a native call (see below)
private native void open0(String name) throws FileNotFoundException;
Digging deeper, into the native call in FileInputStream.c
JNIEXPORT void JNICALL
Java_java_io_FileInputStream_open0(JNIEnv *env, jobject this, jstring path) {
fileOpen(env, this, path, fis_fd, O_RDONLY);
}
Therefore the name is what becomes the path that the native fileOpen method will use. This translates to file.getPath(), which is different from file.getAbsolutePath().
file.getPath() with file as new File("test.txt") returns test.txt, which may not be found.
That's the best I can do, I hope it helps.
See this bug report and this question. In short, setting the user.dir via the command line is bad news.
You are getting FileNotFound exception because the program is not able to find the file you are trying to read (In your case fileName is also "file").
The problem is coming because you have defined only the file name not the path. You should either give absolute or relative path for it to make work from any directory. In absence of the path definition the program will try to read from a file in current directory from where your command is executing.
Let's dive into the details:
you have the text file in path : c:/users/my/project/file
You have your Java file in path : c:/users/my/project/MyClass
now when you run inside c:/users/my/project directory , you get the expected output because the text file "file" is defined in this directory only.
when you switch to c: and try to run the program, you get exception because it is trying to find "c:/file" which does not exist.
try to change the line to mention absolute path instead:
System.out.println(new BufferedReader(new FileReader("c:/users/my/project/file")).readLine());
What is the difference between the following two methods for creating a file?
new File(System.getProperty("user.dir"));
new File("");
Java identifies the first one as a directory, and the second one's neither a file nor a directory! Why is that the case?
Code:
public class MainClass {
public static void main(String[] args) throws Exception {
System.out.println("File Created with CurrentDir taken From System Props");
File f1 = new File(System.getProperty("user.dir"));
System.out.println("Absolute Path: " + f1.getAbsolutePath());
System.out.println("isDirectory: " + f1.isDirectory());
System.out.println("isFile: " + f1.isFile());
System.out.println();
System.out.println("File Created with Empty String Path");
File f2 = new File("");
System.out.println("Absolute Path: " + f2.getAbsolutePath());
System.out.println("isdirectory: " + f2.isDirectory());
System.out.println("isFile: " + f2.isFile());
}
}
Output:
File Created with CurrentDir taken From System Props
Absolute Path: D:\Java Workspace\my_Workspace\JavaTest
isDirectory: true
isFile: false
File Created with Empty String Path
Absolute Path: D:\Java Workspace\my_Workspace\JavaTest
isdirectory: false
isFile: false
Explanation
It may seem a little non-intuitive but actually that's just how the class is supposed to work according to its documentation. It's called empty abstract pathname in the documentation:
The empty abstract pathname has no prefix and an empty name sequence.
And from your constructor File#File(String):
Creates a new File instance by converting the given pathname string into an abstract pathname. If the given string is the empty string, then the result is the empty abstract pathname.
So the File class actually interprets the empty name as actual name. When you test File#isDirectory() or File#isFile() it thus checks if there exists a file or directory like
D:\Java Workspace\iTAW_Workspace\JavaTest\<empty>
Note the <empty> which I wrote to indicate that it actually searches for a file here with the empty name. Obviously such a file can not exist, thus the result will always be false. So again, it does not check
D:\Java Workspace\iTAW_Workspace\JavaTest\
but rather the empty file in this directory, which does not exist.
Unfortunately you don't see this when using the File#toAbsolutePath() method as there is no representation for an empty name.
NIO
Note that the class File and everything related to it is outdated. Nowadays file IO is done using NIO revolving around Files, Paths and Path. This API is much more cleaner and more intuitive. It will also work as intended on your current example:
Files.isDirectory(Paths.get("")); // true
Take a look at the documentation for more.
Creating a file with empty string results to creating a File instance which actually does not exist and its absolute pathname is "empty abstract pathname".
-> That's why the second one's neither a file nor a directory for you.
The reason behind that, a maybe little bit confusing output for you, is definition located in javadocs:
If this abstract pathname is the empty abstract pathname then the
pathname string of the current user directory, which is named by the
system property user.dir, is returned.
You can find more about this topic here
https://docs.oracle.com/javase/6/docs/api/java/io/File.html
You need to make the difference between the Java object File and a file actually present on your computer.
In the first case : new File(System.getProperty("user.dir")). You create a Java object File and give him a path : System.getProperty("user.dir"). Later when you call the function .getAbsolutePath() it returns you the path you gave. Then when you call .isDirectory() it tells you true because there is a directory corresponding to this Java object File.
In the second case, new File("") it creates a Java object File and you give it a path : "". Since the path given is not absolute, the system will resolve it as a relative from the user.dir path.
from documentation
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.
Later when you call the function .getAbsolutePath() it returns you the path you gave, so the path to user dir + empty string : D:\Java Workspace\iTAW_Workspace\JavaTest\<empty>. Then when you call .isDirectory() it tells you false because there is no directory corresponding to this path. (same reason for isFile())
new File("") creates new file with relative (empty) path. As this file doesn't exist both isDirectory() and isFile() return false (corresponds to javadoc).
From javadoc
boolean java.io.File.isDirectory()
...
Returns: true if and only if
the file denoted by this abstract pathname exists and is a directory;
false otherwise
The same is true for isFile(). and as long as your file doesn't exist both methods return false.
This is the code:
String filename = "sql.txt";
File file = new File(filename);
String path = file.getAbsolutePath();
System.out.println(path);
My text file resides in E drive but when I print out the path it is in C drive. Why does this happen?
You have provided a path which is neither absolute nor canonical.
String filename = "sql.txt";
Hence, the pathname is returned as simply the current user directory.
Have a look at the documentation for the getAbsolutePath() method in the File class:
If this abstract pathname is already absolute, then the pathname
string is simply returned as if by the getPath() method. If this
abstract pathname is the empty abstract pathname then the pathname
string of the current user directory, which is named by the system
property user.dir, is returned. Otherwise this pathname is resolved in
a system-dependent way. On UNIX systems, a relative pathname is made
absolute by resolving it against the current user directory. On
Microsoft Windows systems, a relative pathname is made absolute by
resolving it against the current directory of the drive named by the
pathname, if any; if not, it is resolved against the current user
directory.
Follow those steps
Go to run configuration
Click argument tab
Change the working directory to ${workspace_loc:myproject}
Reference
Java workspace and file path
A java class ReadFile1 in the TestA Project. And another class TestRead in project TestB. I want to read that class ReadFile1 in TestRead class. I have the only relative path, then how can i read that.
Example
My class is present in
D:\EIX-New-Source\source\message-kernel\src\main\java\com\eix\transform\parser\MessageTransformer.java
message-kernel is the project in source folder.
and I am doing the test in
D:\EIX-New-Source\source\msg-Test\src\com\coreJava\rnd\RelativePath.java
when I run this program then I got the result as
D:\EIX-New-Source\source\message-kernel\target\classes
But I am expecting the result should be
D:\EIX-New-Source\source\message-kernel\src\main\java\com\eix\transform\parser\MessageTransformer.java
Try the below method for getting the absolute path of your class file and then you can append the remaining path from relative file path to get the actual absolute path of your file.
String getAbsolutePath(){
java.security.ProtectionDomain pd =
YourClassName.class.getProtectionDomain();
if ( pd == null ) return null;
java.security.CodeSource cs = pd.getCodeSource();
if ( cs == null ) return null;
java.net.URL url = cs.getLocation();
if ( url == null ) return null;
java.io.File f = new File( url.getFile() );
if (f == null) return null;
return f.getAbsolutePath();
}
You did not mention what you want to do after reading the file. You can read the file by create a input stream. The input stream works for relative path also.
FileInputStream inputStream = new FileInputStream(new File("../../com/eix/cromics/tdlr/ReadFile1"));
If you want to use it as java api then you need to define the dependency of project TestB on TestA.
Firstly, Java save any file relative to the current working directory.If you give a package declaration then it will create the folder accordingly inside the current directory.
If you always want files to be saved relative to the location of the Java files and not the current working directory, you need to find that directory and pretend it to get an absolute path.
The working directory is where you run the program from i.e. where you call java TestClass, so when you want to write files relative to the class that's executing you'll have to know the current directory and append the relative path from there e.g.
public class TestClass {
public void printFullPath() {
String fullPath = String.format("%s/%s", System.getProperty("user.dir"), this.getClass().getPackage().getName().replace(".", "/"));
System.out.println(fullPath);
}
}
For more details visit How to use relative path instead of absolute path?
I have a project with 2 packages:
tkorg.idrs.core.searchengines
tkorg.idrs.core.searchengines
In package (2) I have a text file ListStopWords.txt, in package (1) I have a class FileLoadder. Here is code in FileLoader:
File file = new File("properties\\files\\ListStopWords.txt");
But I have this error:
The system cannot find the path specified
Can you give a solution to fix it?
If it's already in the classpath, then just obtain it from the classpath instead of from the disk file system. Don't fiddle with relative paths in java.io.File. They are dependent on the current working directory over which you have totally no control from inside the Java code.
Assuming that ListStopWords.txt is in the same package as your FileLoader class, then do:
URL url = getClass().getResource("ListStopWords.txt");
File file = new File(url.getPath());
Or if all you're ultimately after is actually an InputStream of it:
InputStream input = getClass().getResourceAsStream("ListStopWords.txt");
This is certainly preferred over creating a new File() because the url may not necessarily represent a disk file system path, but it could also represent virtual file system path (which may happen when the JAR is expanded into memory instead of into a temp folder on disk file system) or even a network path which are both not per definition digestable by File constructor.
If the file is -as the package name hints- is actually a fullworthy properties file (containing key=value lines) with just the "wrong" extension, then you could feed the InputStream immediately to the load() method.
Properties properties = new Properties();
properties.load(getClass().getResourceAsStream("ListStopWords.txt"));
Note: when you're trying to access it from inside static context, then use FileLoader.class (or whatever YourClass.class) instead of getClass() in above examples.
The relative path works in Java using the . specifier.
. means same folder as the currently running context.
.. means the parent folder of the currently running context.
So the question is how do you know the path where the Java is currently looking?
Do a small experiment
File directory = new File("./");
System.out.println(directory.getAbsolutePath());
Observe the output, you will come to know the current directory where Java is looking. From there, simply use the ./ specifier to locate your file.
For example if the output is
G:\JAVA8Ws\MyProject\content.
and your file is present in the folder "MyProject" simply use
File resourceFile = new File("../myFile.txt");
Hope this helps.
The following line can be used if we want to specify the relative path of the file.
File file = new File("./properties/files/ListStopWords.txt");
InputStream in = FileLoader.class.getResourceAsStream("<relative path from this class to the file to be read>");
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String line = null;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (Exception e) {
e.printStackTrace();
}
try .\properties\files\ListStopWords.txt
I could have commented but I have less rep for that.
Samrat's answer did the job for me. It's better to see the current directory path through the following code.
File directory = new File("./");
System.out.println(directory.getAbsolutePath());
I simply used it to rectify an issue I was facing in my project. Be sure to use ./ to back to the parent directory of the current directory.
./test/conf/appProperties/keystore
While the answer provided by BalusC works for this case, it will break when the file path contains spaces because in a URL, these are being converted to %20 which is not a valid file name. If you construct the File object using a URI rather than a String, whitespaces will be handled correctly:
URL url = getClass().getResource("ListStopWords.txt");
File file = new File(url.toURI());
Assuming you want to read from resources directory in FileSystem class.
String file = "dummy.txt";
var path = Paths.get("src/com/company/fs/resources/", file);
System.out.println(path);
System.out.println(Files.readString(path));
Note: Leading . is not needed.
I wanted to parse 'command.json' inside src/main//js/Simulator.java. For that I copied json file in src folder and gave the absolute path like this :
Object obj = parser.parse(new FileReader("./src/command.json"));
For me actually the problem is the File object's class path is from <project folder path> or ./src, so use File file = new File("./src/xxx.txt"); solved my problem
For me it worked with -
String token = "";
File fileName = new File("filename.txt").getAbsoluteFile();
Scanner inFile = null;
try {
inFile = new Scanner(fileName);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
while( inFile.hasNext() )
{
String temp = inFile.next( );
token = token + temp;
}
inFile.close();
System.out.println("file contents" +token);
If text file is not being read, try using a more closer absolute path (if you wish
you could use complete absolute path,) like this:
FileInputStream fin=new FileInputStream("\\Dash\\src\\RS\\Test.txt");
assume that the absolute path is:
C:\\Folder1\\Folder2\\Dash\\src\\RS\\Test.txt
String basePath = new File("myFile.txt").getAbsolutePath();
this basepath you can use as the correct path of your file
if you want to load property file from resources folder which is available inside src folder, use this
String resourceFile = "resources/db.properties";
InputStream resourceStream = ClassLoader.getSystemClassLoader().getResourceAsStream(resourceFile);
Properties p=new Properties();
p.load(resourceStream);
System.out.println(p.getProperty("db"));
db.properties files contains key and value db=sybase
If you are trying to call getClass() from Static method or static block, the you can do the following way.
You can call getClass() on the Properties object you are loading into.
public static Properties pathProperties = null;
static {
pathProperties = new Properties();
String pathPropertiesFile = "/file.xml";
// Now go for getClass() method
InputStream paths = pathProperties.getClass().getResourceAsStream(pathPropertiesFile);
}