Getting a file object of a directory - java

I need a File object pointing to a directory (may not be existing). How do I do that?
Even if I do something like
File dir = new File("/tmp/something/"); // with trailing slash
dir.isDirectory() is false. Then I tried dir.mkdir() which returns false, why? I dont need the directory to be existing, in fact, I want it to point to a directory that does not exist (I am doing testing). How can I achieve this?

from javadoc: "true if and only if the file denoted by this abstract pathname exists and is a directory"
If the file does not exists isDirectory() return false. If you are doing testing probably use a stub can be a better option, in unit testing its better try to don't touch external resources like the filesystem.

Use dir.mkdirs()
mkdirs() will create the specified directory path in its entirety where mkdir() will only create the bottom most directory, failing if it can't find the parent directory of the directory it is trying to create.

Trailing slash does not matter. File.isDirectory returns false because it returns true if and only if the file denoted by this abstract pathname exists and is a directory

Related

How to treat java package as a File folder?

I want to be able to iterate through a package of files as if the package were a folder.
Something like the below (scripts being the java package):
File scriptFolder = new File("scripts").getAbsoluteFile();
The packages appear are not being treated like folders. If I hardcode the path C:\Users\...\project_folder\...\scripts the File.isFile() method returns false for the package. If I do new File (C:\Users\...\project_folder\...\scripts\script).isFile() I get true.
I want to get a File of the folder so I can get a list of the files in the folder and iterate through it.
The .isFile() method returns true only if you are referencing a plain jane normal file. If you're referencing a directory, it'd return false. Try .isDirectory() or possibly .exists().
Or don't; there's no real need:
File[] filesInDir = new File("C:\\Users\\....\\scripts").listFiles();
if (filesInDir == null) {
// this means it wasn't a directory or didn't exist or isn't readable
} else {
for (File child : filesInDir) {
// called for each file in dir
}
}
The official javadocs say this about File#isFile():
Tests whether the file denoted by this abstract pathname is a normal file. A file is normal if it is not a directory and, in addition, satisfies other system-dependent criteria. Any non-directory file created by a Java application is guaranteed to be a normal file.
You can check if it is a directory with File#isDirectory(), then if it is, you can list its contents with File#listFiles().
Unless I'm missing something in your question C:\Users...\project_folder...\scripts is a directory so isFile() will return false because it is not a file.

Empty File constructor is neither file nor directory

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.

How do I distinguish between a file and a folder when renaming a file/folder in java

I am currently programming a file name normaliser. Files have a format and folders dont. When I rename a file I need to make sure that I do not affect the format therefore I did
fileName.substring(fileName.lastIndexOf("."),fileName.length)
thereby if I want to replace all the periods in a fileName it does not affect the format, when a folder with periods in its name goes through this process, the last instance of the period is still part of its name, therefore it does not replace all the dots in the folders name. I need to know how to distinguish between a file and a folder so I can fix this.
You can use
someFile.isDirectory();
It returns true if the file is a folder, and false if not.
You can use File.isDirectory() to test whether the file denoted by this abstract pathname is a directory. You can also use File.isFile() to test whether the file denoted by this abstract pathname is a normal file. A file is normal if it is not a directory and, in addition, satisfies other system-dependent criteria.
File f = new File(fileName);
if (f.isFile()) {
// it's a file.
} else if (f.isDirectory()) {
// it's a directory.
}

How to get to a file by passing relative path in java?

I am trying to understand "How to get to file by passing relative path of a file or folder?" . Here is the example:
CODE:
public class somex {
public static void main {
String fileName = System.getProperty("user.dir"); <---This gives me path for the current working directory.
File file = new File(fileName + "../../xml_tutorial/sample.xlsx" );
System.out.println(file.getCanonicalPath()); <---This gives me path for the file that is residing in folder called "xml_tutorial".
}
}
>>>>
Here, I know the file location so i was able to pass correct relative path. And, managed to print the file path. I have deleted the "sample.xlsx" and executed the above code; With no failing it gives me the path name and it is same path as when the file exists (i.e. before deleting). How it is possible ? I am expecting EXCEPTION here. why it is not throwing exception ?
Two, I want to use regular expression for the file name, such as: "../../xml_tutorial/samp.*". But this doesn't do the job and it gives me IOException. Why it is not able to identify the file sample.xlsx ? (NOTE: this is when the file exist and one hundred precent sure there is only one file with the name "sample.xlsx")
I have deleted the "sample.xlsx" and executed the above code; With no failing it gives me the path name and it is same path as when the file exists (i.e. before deleting). How it is possible ? I am expecting EXCEPTION here. why it is not throwing exception ?
File doesn't care whether the file actually exists. It just resolves the path. There's no need for the file to exist in order to take the path
/home/tjc/a/b/c/../../file.txt
...and turn it into the canonical form
/home/tjc/a/file.txt
If you want to know whether the file on that path actually exists, you can use the exists() method.
On your second, unrelated question:
Two, I want to use regular expression for the file name, such as: "../../xml_tutorial/samp.*". But this doesn't do the job and it gives me IOException. Why it is not able to identify the file sample.xlsx ?
There's nothing in the File documentation saying that it supports wildcards. If you want to do searches, you'll want to use list(FilenameFilter) or listFiles(FilenameFilter) and a FilenameFilter implementation, or listFiles(FileFilter) and a FileFilter implementation.

Java isFile(), isDirectory() without checking for existence

I want to check if a given String is a file or a directory, i've tried the methods isFile() and isDirectory() of the File class but the problem is that if the directory or file doesn't exist these methods returns false, because as stated in the javadoc :
isFile() :
true if and only if the file denoted by this abstract pathname exists
and is a normal file; false otherwise
isDirectory() :
true if and only if the file denoted by this abstract pathname exists
and is a directory; false otherwise
Basically i need two methods without the exist clause ...
So i want to test if the given string complies to a directory format or complies to a file format, in a multiplatform context (so, should work on Windows, Linux and Mac Os X).
Does exist some library that provide these methods ? What could be the best implementation of these methods ?
UPDATE
In the case of a string that could be both(without extension) by default should be identified as directory, if a file with that path does not exist.
So i want to test if the given string complies to a directory format or complies to a file format, in a multiplatform context (so, should work on Windows, Linux and Mac Os X).
In Windows, a directory can have an extension and a file is not required to have an extension. So, you can't tell just by looking at the string.
If you enforce a rule that a directory doesn't have an extension, and a file always has an extension, then you can determine the difference between a directory and a file by looking for an extension.
Why not just wrap them in a call to File#exists()?
File file = new File(...);
if (file.exists()) {
// call isFile() or isDirectory()
}
By doing that, you've effectively negated the "exists" portion of isFile() and isDirectory(), since you're guaranteed that it does exist.
It's also possible that I've misunderstood what you're asking here. Given the second part of your question, are you trying to use isFile() and isDirectory() on non-existent files to see if they look like they're files or directories?
If so, that's going to be tough to do with the File API (and tough to do in general). If /foo/bar/baz doesn't exist, it's not possible to determine whether it's a file or a directory. It could be either.
Sounds like you know what you want, according to your update: if the path doesn't exist and the path has an extension it's a file, if it doesn't it's a directory. Something like this would suffice:
private boolean isPathDirectory(String myPath) {
File test = new File(myPath);
// check if the file/directory is already there
if (!test.exists()) {
// see if the file portion it doesn't have an extension
return test.getName().lastIndexOf('.') == -1;
} else {
// see if the path that's already in place is a file or directory
return test.isDirectory();
}
}
There are rules for what is invalid in a file and/or folder name. For example, Windows doesn't allow *, ?, and a few other characters. Based on what's invalid, you could build a regex expression or some other process/checking system to see if it looks like a file or folder.
This could get complex as you want it to work for many different OS's. Also, as previously posted, there would be no way to tell a file from a folder unless you artificially enforced a convention. For example, directories must end in a front-slash / in Windows.
Having the IF EXISTS check first would help. If IF EXISTS = true, then running the existing File.isDirectory() or File.isFile() code would simplify a lot of this. You would only have to write code for when IF EXISTS = false.

Categories

Resources