| How
To Find a File Fall 2006, David Matuszek |
Suppose you want to access (read or write) a file. This should be simple. It isn't.
Suppose, for example, we want to read the text file dummy.txt and
print its contents. The following code should work--and just to make
matters worse, it often does work--but you cannot depend on it.
FileReader r = new FileReader("dummy.txt");
BufferedReader b = new BufferedReader(r);
String line;
while((line = b.readLine()) != null) {
System.out.println(line);
}
b.close();
r.close(); |
The problem is this line:
FileReader r = new FileReader("dummy.txt"); |
You expect that "dummy.txt" is a relative path name, and it is.
You also expect it to be relative to the directory that holds your main class--but
it isn't. It's relative to the current directory, which is the directory
from which you (or your IDE) started Java. This may or may not be the same
as the directory holding your main class.
This is my usual workaround. Just open a JFileChooser and ask
the user to find the file for you. It's simple and it always works.
However, if you want to open the same file every time--maybe it's an initialization file--you don't want to ask the user to open it for you. Most especially, you don't want to give the user directions on which file to open; the user will think (correctly) that if the program knows which file to open, it should just open it.
One way around this is to use absolute path names. For example:
String dir1 = "C:/Documents and Settings/Matuszek/"; String dir2 = "My Documents/workspace/MyProject"; String fileName = "dummy.txt"; FileReader r = new FileReader(dir1 + dir2 + "/" + fileName); |
This is a terrible solution.
Do not use absolute path names!
As noted above, you would normally want to use paths relative to the directory containing your main class, not the directory from which Java was started. Therefore, you need to know what directory the main class is in. To do this:
Class object for the main class (or any class in
the directory you want to start from).
Class myClass = getClass(); works in any instance method.Class myClass = myObject.getClass(); works for any
object.Class myClass = MyClass.class; works (even in static
methods) when you know the name of the class).Class myClass = forName("MyClass"); works
when you know the class name as a String.import java.net.URL;ClassLoader loader = myClass.getClassLoader();URL myURL = loader.getResource("dummy.txt"); String path = myURL.getPath(); %20. That doesn't work in a path; you have to turn
each %20 back
into a space.
path = path.replaceAll("%20", " "); FileReader r = new FileReader(path); Putting this all together, and leaving out the unnecessary variables, we have:
FileReader r = new FileReader(RelativeFile.class.getClassLoader()
.getResource("dummy.txt").getPath()
.replaceAll("%20", " ")); |
See? Nothing to it!