How to specify a directory when creating a File object? - java

This should be a really simple question but Google + my code isn't working out.
In Eclipse on Windows, I want my program to look inside a certain folder. The folder is directly inside the Project folder, on the same level as .settings, bin, src, etc. My folder is called surveys, and that's the one I want my File object to point at.
I don't want to specify the full path because I want this to run on both of my computers. Just the path immediately inside my Project.
I'm trying this code but it isn't working - names[] is coming back null. And yes I have some folders and test junk inside surveys.
File file = new File("/surveys");
String[] names = file.list();
for(String name : names)
{
if (new File("/surveys/" + name).isDirectory())
{
System.out.println(name);
}
}
I'm sure my mistake is within the String I'm passing to File, but I'm not sure what's wrong?

In your question you didn't specify what platform you are running on. On non-Windows, a leading slash signifies an absolute path. Best to remove the leading slash. Try this:
File file = new File("surveys");
System.out.println("user.dir=" + System.getProperty("user.dir"));
System.out.println("file is at: " + file.getCanonicalPath());
String[] names = file.list();
for(String name : names)
{
if (new File(file, name).isDirectory())
{
System.out.println(name);
}
}
Make sure the in your run configuration, the program is running from the projects directory (user.dir = <projects>)

Make sure that your file is a directory before using file.list() on it, otherwise you will get a nasty NullPointerException.
File file = new File("surveys");
if (file.isDirectory()){
...
}
OR
if (names!=null){
...
}

If you checked the full path of your file with
System.out.println(file.getCanonicalPath())
the picture would immediately become clear. File.getCanonicalPath gives you exactly the full path. Note that File normalizes the path, eg on Windows "c:/file" is converted to "C:\file".

Related

Directory and Filename Concatenating does NOT work

I am working in Netbeans IDE.
What I want to do is:
Get The directory of the Current Java Application (Ex: "F:\PadhooWorld")
Join a file name to it. (Ex: "\Somestuff.txt")
Check if that File exists (Ex: "F:\PadhooWorld\Somestuff.txt")
Do a if.. else activity
When I tam trying to Join Directory + Filename, it is throwing lots of error messages like Path cannot be converted to string etc . Searching the net the whole day, doesn't yield any simple usable solution
Please specify a very simple solution.
EDIT
I have only 2 lines of code as yet
String AppPath = System.getProperty("user.dir");
String fullPath = AppPath + "\Surabhi.txt";
The First Line resolves alright
The Second line (I tried different variations) No Luck. It is underlined in red. Error hints say stuffs like 'Path cannot be converted to string'..
I cannot RUN the code.
It sounds like you're overthinking it. You can just create a File object with the file name you want (the path to the current directory will be used by default) and then call exists() on it:
File f = new File("filename.txt");
System.out.println(f.getAbsolutePath()); //Just for debug if you want to check the path
if(f.exists()) {
//Whatever
}
Alternatively, if you want to specify the path as well as the file name:
String AppPath = System.getProperty("user.dir");
String fileName = "Surabhi.txt";
File f = new File(AppPath, fileName); //f.getAbsolutePath() will give the concatenated name
if(f.exists()) {
//Whatever
}

Reading .txt File From Relative Path in Java

I know this question has been asked in a myriad of variations, but today I wish to emphasize one particular scenario when one wishes to read from a .txt file without specifying the absolute path.
Suppose we have the following set up in Eclipse.
projectName/packageName/subPackage/
and we have a class named Read.java inside the subPackage. The class will be attempting to read from the input1.txt.
We also have input1.txt inside the very same subPackage.
If one uses absolute paths, the code inside Read.java will be something of the following (let's assume now that input1.txt is placed on my Desktop for illustration purposes):
// Create a list to store the list of strings from each line of the input1.txt.
LinkedList<String> inputStrings = new LinkedList<String>();
BufferedReader bufferedTextIn = null;
try {
String line;
// Specify the file
String fileName = "C:" + File.separator
+ "Users" + File.separator
+ "Kevin" + File.separator
+ "Desktop" + File.separator
+ "input1.txt";
bufferedTextIn = new BufferedReader(new FileReader(fileName));
while ((line = bufferedTextIn.readLine()) != null) {
inputStrings.add(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (bufferedTextIn != null) {
bufferedTextIn.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
The problem with the above is the use of absolute paths to my desktop. If I passed the code to my friend, he would need to manually change the path to his desktop. Even if I put input1.txt in my project folder, my friend would still need to manually change the path to make it work.
Note that using File.separator is a good practice because different OS interprets separators a bit differently, but it is still insufficient.
So what do we do instead?
Here is my solution.
String fileName = Read.class.getResource("input1.txt").getPath();
System.out.println(fileName);
bufferedTextIn = new BufferedReader(new FileReader(fileName));
Let's recap the scenario. We have our input1.txt file placed in the SAME FOLDER as the Read.java. So, the code above attempts to go to where Read.class exists (which is somewhere in the bin folder in Eclipse), and look for input1.txt. This is the path RELATIVE to where Read.class is located (in this case, it is trivially in the same folder, but you could very well specify another folder relative to where Read.class is located). The print statement lets you know exactly where it is located and is a good practice while debugging.
When you build in Eclipse, the .java files in the src folder would be compiled into .class files and be placed in the bin folder. The neat thing is that input1.txt is ALSO copied over the bin folder (and all the package hierarchies are maintained).
An important thing to note is to use getPath() rather than toString(), because the latter will add some extra text to the front of the path (I only knew that because I printed it out) and thus you get a NULL pointer exception because the fileName was not formatted correctly.
Another important thing to note is that I used Read.class.getResource("input1.txt").getPath(); instead of this.getClass().getResource("input1.txt").getPath(); because the code was called in a static context (in my main method). If you create an object, then feel free to use the latter.
If you're interested in more advanced features, you can check out the link below:
What is the difference between Class.getResource() and ClassLoader.getResource()?
I hope this helps!
Edit:
You could use the following to get the directory where Read.class resides in also.
String fileName = Read.class.getResource(".").getPath();
Specifying getResource("..") would go to the parent directory.
String fileName = Read.class.getResource("..").getPath();
The above may be useful if you want to have more control specifying the path (e.g. if you want to create output.txt inside the directory where Read.class resides, use
String fileName = Read.class.getResource(".").getPath() + "output.txt";
If you knew the file was going to be located in the same folder in each system this program was run on, you could use system variables to ensure any path defined would still work with different users. For windows, I've used:
String user = new com.sun.security.auth.module.NTSystem().getName();
to get a user name. This could then be substituted in your example to be:
String fileName = "C:" + File.separator
+ "Users" + File.separator
+ user + File.separator
+ "Desktop" + File.separator
+ "input1.txt";
I'm not sure how this would work outside of Windows however.

Deleting certain folders within a directory java

Say I have a list of folders' names within a directory that has the path
C:\Users\Desktop\Application\('folder_names')
How would I delete certain folders within this directory and keep the ones I have stored in a list.
ie. I have a String List:
String[] deleteList = "folder 1, folder 2, folder 3";
and in the directory:
C:\Users\Desktop\Application\ I only want to delete folder 2
How might I do this using the String List instead of explicitly call out that folder?
So far I have:
UPDATED:
File[] deleteList = directory.listFiles(fileFilter);
for (File file : deleteList) {
if (file.isDirectory()) {
System.out.println(file.getPath());
if (file.getPath()
.equals("C:\\Users\\Desktop\\Application\\folder 2")) {
System.out.println("got folder");
FileUtils.deleteDirectory(file);
} else {
System.out.println("Didn't get it.");
}
}
}
Output
C:\Users\U201165\Desktop\Newfolder\Newfolder(2)
got folder
C:\Users\U201165\Desktop\Newfolder\Newfolder(3)
Didn't get it.
C:\Users\U201165\Desktop\Newfolder\Newfolder(4)
Didn't get it.
C:\Users\U201165\Desktop\Newfolder\Newfolder(5)
Didn't get it.
You are probably getting a relative path from the getPath(). To be sure that you are getting the absolute path from the File object, use:
if (file.getAbsolutePath().equals("C:\\Users\\Desktop\\Application\\folder2")) ...
instead of getPath().
Your System.out is showing the file object, but in your equals method you are using file.getPath(). Put file.getPath() in your system.out so you can see what you are actually comparing. The File object has a method like getExplicitPath() method. You might need to be using that instead of path. In some cases I think path just shows the file name, or the relative path not the expect one.

Java File.renameTo(File) not working

I'm trying to list a directory's contents, and rename certain files.
public void run(String dirName) {
try {
File parDir = new File(dirName);
File[] dirContents = parDir.listFiles();
// Rename if necessary
for(File f : dirContents) {
System.out.println("f is:\n" + f.toString());
String name = f.getName();
String subbedName = name.replaceAll("\uFFFD", "_");
System.out.println("\n" + "name = " + name + ", subbedName = " + subbedName + "\n");
if(!name.equals(subbedName)) {
File newFile = new File(f.getParentFile(), subbedName);
System.out.println("newFile is:\n" + newFile.toString());
if(!f.renameTo(newFile))
System.out.println("Tried to change file name but couldn't.");
}
}
}
catch(Exception exc1) {
System.out.println("Something happened while listing and renaming directory contents: " + exc1.getMessage());
}
}
When I run this, I get "Tried to change file name but couldn't." I don't believe that Java is considering these files to be "open", so I don't think that's the reason. I've even ran chmod 777 myDir where myDir is the value of the dirName string passed into the run method.
What am I missing here? Why won't Java rename these file(s)? These are CentOS machines.
Edit: Added printouts for both f and newFile, which is as follows:
f is:
/root/path/to/mydir/test�.txt
newFile is:
/root/path/to/mydir/test_.txt
You need to create your new File object with the full pathname of those files. So
String name = f.getName(); // gets the name without the directory
should likely be:
String name = f.getAbsolutePath();
(your search/replace may need to change)
The problem is that f.getName() returns the last name component of the path that is represented by f. You then massage this String and turn it back into a File. But the File now represents a path relative to the current directory, not the directory containing the original path.
As a result your code is actually attempting to rename the files from dirName into the application's current directory. That could fail because files already exist in the current directory with those names, or because the dirName and the current directory are in different file systems. (You cannot rename a file from one filesystem to another ... you have to copy it.)
Please note that a File in Java represents a pathname, not a file or a folder. In your code, the f objects are the pathnames for file system objects (either files or folders) in the directory denoted by the String dirname. Each of these f objects will have a directory part.
There is more than one way to fix your code; for example
change name = f.getName() to name = f.toString()
change new File(subbedName) to new File(f.getParentFile(), subbedName)
I have an alternative / additional theory.
The pathname of the file containing the \uFFFD character is coming out as "mojibake"; i.e. the kind of garbled text that you get when you display encoded text using the wrong encoding. And since we are seeing 3 characters of garbled text, I suspect that it is attempting to display the UTF-8 rendering of \uFFFD as Latin-1.
So my theory is that the same think is happening when the File.renameTo method is converting f to the form that it is going to provide to the system call. For some reason that is no clear to me, Java could be using the wrong encoding, and as a result producing a "name" for the original file that doesn't match the name of the file in the file system. That would be sufficient to cause the rename to fail.
Possibly related questions / links:
File name charset problem in java
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4733494 (Note that Sun decided this was not a Java bug, and most of the "me too" comments on the bug report are from people who do not understand the explanation ...)
f.getName(); only returns the name of the folder, not the full path. So subbedName becomes a relative path file. Try something with f.getCanonicalPath() instead.

How to enter a directory as an argument in Eclipse

Basically, I have a directory with some files in it. In run configurations I am trying to put the directory as an arguement like so: \(workspacename\directory. Then, the following code should create a list of all the files in that directory:
String directory = args[1];
File folder = new File(directory);
File[] allFiles = folder.listFiles();
ArrayList<File> properFiles = null;
for (File file: allFiles) {
if(file.getName().endsWith(".dat")){
properFiles.add(file);
}
}
the problem i'm facing is that for some reason allFiles is null.
I'll take a guess at what your problem might be:
If your argument is a relative path (as opposed to an absolute path, staring with "/" or "c:/" for example), keep in mind that files will be relative to the working directory of the application.
So new File(directory) will be relative to wherever the application is started. In Eclipse the default working directory is in the project. So if your project is in the top level of the workspace, it will be something like workspacename/project.
You can try printing out folder.getAbsolutePath(), folder.exists() and folder.isDirectory() to help diagnose your problem.
The javadocs say listFiles() will return null if the directory does not actually exist (among other things):
Returns null if this abstract pathname does not denote a directory, or if an I/O error occurs.
Debug by verifying (debugger or printf) the args[1] value.
Also, it looks like you might be trying to use a substitution variable to insert the workspace location in the path. If so, again, you need to verify (via debugger or printf) that the placeholder is getting replaced properly.

Categories

Resources