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());
Related
private void copyFile() throws IOException {
Path destination;
String currentWorkingDir = System.getProperty("user.dir");
File fileToCopy = component.getArchiveServerFile();
if (path.contains(File.separator)) {
destination = Paths.get(path);
} else {
destination = Paths.get(currentWorkingDir + File.separator + path);
}
if (!Files.exists(destination)) {
try {
Files.createDirectories(destination);
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
FileUtils.copyFileToDirectory(fileToCopy, new File(destination.toString()));
}
}
Basically what I'm trying to do here is copying a file in some location using the path provided in the class's constructor. The logic is like this:
If the path has file separator, I consider it a full path and copy the file at the end.
If the path doesn't have file separator, I copy the file in the working directory from which the .exe file was launched.
So far, only the first option works (the full path). For some reason, the working directory option is not working and I can't figure out why.
UPDATE: If I just change the following line:
String currentWorkingDir = System.getProperty("user.dir");
to
String currentWorkingDir = System.getProperty("user.home");
It works. So I'm guessing the problem is coming from user.dir? Maybe at runtime, the folder is already being used and as a result, it can't copy the file into it?
The weird thing is, I don't have any exceptions or error, but nothing happens as well.
UPDATE 2: I think the problem here is that I'm trying to copy a file which is embedded in the application (.exe file) that I'm executing during runtime, and java can't copy it while the current working directory is being used by the application.
UPDATE 3:
Since this copy method is used in an external library, I had to come up with another way (other than logs) to see the content of system property user.dir. So I wrote I little program to create a file and write in it the value return by the property.
To my surprise, the path is not where my application was launched. It was in:
C:\Users\jj\AppData\Local\Temp\2\e4j1263.tmp_dir1602852411
Which is weird because I launched the program from :
C:\Users\jj\workspace\installer\product\target\
Any idea why I'm getting this unexpected value for user.dir?
EDIT: to run my code i am using "java filename.java input1.txt" is this correct?
I am creating a program where i have to tokenize a string into separate words and that string is in a text file. I have to specify the text file name in the terminal through command line arguments (args[0], etc). I am able to scan and print the content of the text file if i specify through paths but when i try to do it using args[0] it doesn't seem to work. I am using net beans. I will attach my section of code here:
public static void main(String[] args) {
try {
File f = new File(args[0]);
//using this commented out section using paths works File f = new
//File("NetBeansProjects/SentenceUtils/src/input1.txt");
Scanner input = new Scanner(new FileInputStream(f));
while(input.hasNext()) {
String s = input.next();
System.out.println(s);
}
} catch(FileNotFoundException fnfe) {
System.out.println("File not found");
}
SentenceUtils s = new SentenceUtils();
}
java filename.java input1.txt
is not correct for running a java program, you need to compile the *.java file to get a *.class file which you can then run like:
java filename input1.txt
assuming your class is in the default package and you are running the command in the output directory of your compile command, or using the fully qualified class name of the class, i.e. including the package name. For example if your class is in the package foo/bar/baz (sub folders in your source folder) and has the package declaration package foo.bar.baz;, then you need to specify your class like this:
java [-cp your-classpath] foo.bar.baz.filename input1.txt
for input1.txt to be found it has to be in the same directory where you run the command.
your-classpath is a list of directories separated by a system dependent delimiter (; for windows, : for linux, ...) or archives which the java command uses to look up the class to run specified and its dependencies.
NetBeansProjects/SentenceUtils/src/input1.txt is a relative path.
File f = new File("NetBeansProjects/SentenceUtils/src/input1.txt");
if this works then it means that the current working directory (i.e. the directory from which all relative paths are calculated) is the the rectory named NetBeansProjects.
You get FileNotFoundException because your file is expected to be in
NetBeansProjects/input1.txt
To find out which is the current working directory for your running program you can add the following statement:
System.out.println(new File("").getAbsolutePath());
Place input.txt in that directory and it will be found.
Alternatively you can pass the absolute path of your input file. an absolute path is a path that can be used to locate your file from whatever location your program is running from on your local filesystem. For example:
java -cp <your-classpath> <fully-qualified-name-of-class> /home/john/myfiles/myprogects/...../input1.txt
To sum up, what you need to know/do is the following:
the location of your program class and its package (filename)
the location of your input file (input.txt)
pass the correct argument accordingly
Can you help me to get the correct file path? I give in the arguments a link to a file with the name:
GovHK 香港政府一站通:Homepage (Residents).webloc
And instead of it I receive:
GovHK ???????:Homepage (Residents).webloc
So I can not get file, file.exists(); returns false
public class Test {
public static void main(String[] args) {
if (args.length > 0) {
File file = new File(args[0]);
System.out.println("Exists: " + file.exists());
}
}
}
File was taken from MacOS to Windows.
You can see the original file here
How can I get the real file path to handle it?
Thank you!
UPD
If I get list of files in the directory, file path is showing correctly and files exist. So the problem is on way cmd -> jar
Thanks to #MikitaBerazouski question, we found out that it is an issue of Windows console encoding.
[UPDATE]
Used JNI to get real command line arguments
import java.io.File;
public class FileDemo {
public static void main(String[] args) {
String sourceDirectory = "~/Documents";
System.out.println(sourceDirectory);
File dir = new File(sourceDirectory);
File[] dirFiles = dir.listFiles();
for (File file : dirFiles)
{
System.out.println( file.getName() );
}
}
}
I am using the code above to list files in the Documents directory in Ubuntu. The same code works if I replace the folder name to a local folder where the Java class file resides. HOwever, I always get NULL Pointer exception when using absolute paths, as the dirFiles is NULL.
Could someone explain if there is any mistake in my approach.
Thanks.
Tilda ~ is not absolute path. It is a feature of typical unix shell to replace it by home directory of current user. In java program you should use System.getProperty ("user.home") instead of tilda.
The problem seems to be with the sourceDirectory. Instead of ~/Documents , try with the complete path /home/foo/Documents
Im trying to write a program to read a text file through args but when i run it, it always says the file can't be found even though i placed it inside the same folder as the main.java that im running.
Does anyone know the solution to my problem or a better way of reading a text file?
Do not use relative paths in java.io.File.
It will become relative to the current working directory which is dependent on the way how you run the application which in turn is not controllable from inside your application. It will only lead to portability trouble. If you run it from inside Eclipse, the path will be relative to /path/to/eclipse/workspace/projectname. If you run it from inside command console, it will be relative to currently opened folder (even though when you run the code by absolute path!). If you run it by doubleclicking the JAR, it will be relative to the root folder of the JAR. If you run it in a webserver, it will be relative to the /path/to/webserver/binaries. Etcetera.
Always use absolute paths in java.io.File, no excuses.
For best portability and less headache with absolute paths, just place the file in a path covered by the runtime classpath (or add its path to the runtime classpath). This way you can get the file by Class#getResource() or its content by Class#getResourceAsStream(). If it's in the same folder (package) as your current class, then it's already in the classpath. To access it, just do:
public MyClass() {
URL url = getClass().getResource("filename.txt");
File file = new File(url.getPath());
InputStream input = new FileInputStream(file);
// ...
}
or
public MyClass() {
InputStream input = getClass().getResourceAsStream("filename.txt");
// ...
}
Try giving an absolute path to the filename.
Also, post the code so that we can see what exactly you're trying.
When you are opening a file with a relative file name in Java (and in general) it opens it relative to the working directory.
you can find the current working directory of your process using
String workindDir = new File(".").getAbsoultePath()
Make sure you are running your program from the correct directory (or change the file name so that it will be relative to where you are running it from).
If you're using Eclipse (or a similar IDE), the problem arises from the fact that your program is run from a few directories above where the actual source is located. Try moving your file up a level or two in the project tree.
Check out this question for more detail.
The simplest solution is to create a new file, then see where the output file is. That is the correct place to put your input file into.
If you put the file and the class working with it under same package can you use this:
Class A {
void readFile (String fileName) {
Url tmp = A.class.getResource (fileName);
// Or Url tmp = this.getClass().getResource (fileName);
File tmpFile = File (tmp);
if (tmpFile.exists())
System.out.print("I found the file.")
}
}
It will help if you read about classloaders.
say I have a text file input.txt which is located on the desktop
and input.txt has the following content
i came
i saw
i left
and below is the java code for reading that text file
public class ReadInputFromTextFile {
public static void main(String[] args) throws Exception
{
File file = new File(
"/Users/viveksingh/desktop/input.txt");
BufferedReader br
= new BufferedReader(new FileReader(file));
String st;
while ((st = br.readLine()) != null)
System.out.println(st);
}
}
output on the console:
i came
i saw
i left