exists() does not work but getAbsolutePath() does work - java

I have the below code whereby I create a File type based on a pre-created file "test.brd" and also call the getAbsolutePath() method on this File, this all works correctly. However, when I run the exists() method, this is deemed as not existing.
When I debug, the status of the File is null and the path is also null, yet the getAbsolutePath() method works. I have debugged and it goes to the Security section of the exists() method.
Please see below:
File inputFile = new File("/Users/myname/Desktop/project_name/test.brd");
// The below works and returns the path
System.out.println(inputFile.getAbsolutePath());
if (inputFile.exists()) {
System.out.println("Exists");
}
else {
System.out.println("Invalid");
}
Even when I construct the file without the absolute path and just give the file name as a parameter (stored locally with Java file) the correct absolute path is provided.
Hope this makes sense. All I want to do is read a pre-created file into an Array, each character is an element in the array, I was intending on using scanner to read the file, but inputFile does not exist to be read.

The two methods are about different aspects of the file:
getAbsolutePath() is about file name. In a way, this is a "string manipulation method" completely separated from the actual file system
exists() is about the actual file. It checks whether or not the file is present in the file system at the location identified by the given path.
Note that getAbsolutePath() and other path manipulation methods of File must work even without the file or the folder being present in the actual file system. Otherwise, the API would not be able to support file creation, e.g. through createNewFile().

If you take a look at the javadoc, you can find the following sentence
Instances of this class may or may not denote an actual file-system object such as a file or a directory.
Proving that the instance in memory of a File object is not necessarily a real file or directory existing in the file system.

File inputFile = new File("/Users/myname/Desktop/project_name/test.brd");
The line above doesn't create a new File and hence it doesn't exists.
If you want to create a file you can use method inputFile.createNewFile().
The method getAbsolutePath() works on the inputFile object and is completely different from file creation.

Related

How to read a file that is located in any location on the computer?

So I have a project, and this is one of the demands:
You should have a class named Project3, containing a main method.
This program reads the levels information from a file whose name is
specified as a command-line parameter (The file should also be
relative to the class-path as described here:)
All the file names specified in the levels and block definition files
should be relative to the class path. The reason we want them to be
relative to the class path is that later we will be able to read the
files from inside a jar, something we can not do with regular File
references.
To get an input stream relative to the class path (even if it's inside
a jar), use the following:
InputStream is =
ClassLoader.getSystemClassLoader().getResourceAsStream("image.png");
The idea is to keep a folder with files(definitions and images) and
then add that folder to the class path when running the JVM:
java -cp bin:resources ... If you don't add the resources folder to
you class path you wont be able to load them with the command from
above.
When run without parameters, your program should read a default level
file, and run the game accordingly. The location of the default level
file should be hard-coded in your code, and be relative to the
classpath_.
When run without parameters, your program should read a default level file, and run the game accordingly. The location of the default level file should be hard-coded in your code, and be relative to the classpath_.
The part of the code that handles the input is:
public Void run() throws IOException {
LevelReader level = new LevelReader();
List<level> chosenLevels = new ArrayList<>();
if (args.length >= 1) {
File f = new File(args[0]);
if (f.exists()) {
chosenLevels = level.makeLevel(args[0]);
}
}
if (chosenLevels.size() == 0) {
game.runLevels(defaultLevels);
} else {
game.runLevels(chosenLevels);
}
return null;
}
So my question is:
An argument should be the full path of a file which means:
D:\desktop\level3.txt
Is it possible to read a file from every location on my computer?
Because right now I can do it only if my text file is in the
project's directory (not even in the src folder).
I can't understand the rest of their demands. What does is mean "should be hard-coded in your code, and be relative to the
classpath_." and why is it related to InputStream method(?)
I'm confused all over this.
Thanks.
A classpath resource is not the same as a file.
As you have correctly stated, the full path of a file is something like D:\desktop\level3.txt.
But if ever want to distribute your application so it can run on other computers, which probably won’t have that file in that location, you have two choices:
Ask the user to tell the program where to find the file on their computer.
Bundle the file with the compiled program.
If you place a non-.class file in the same place as .class files, it’s considered a resource. Since you don’t know at runtime where your program’s class files are located,¹ you use the getResource or getResourceAsStream method, which is specifically designed to look in the classpath.
The getResource* methods have the additional benefit that they will work both when you are developing, and when the program is packaged as a .jar file. Individual entries in a .jar file are not separate files and cannot be read using the File or FileInputStream classes.
If I understand your assignment correctly, the default level file should be an application resource, and the name of that resource is what should be hard-coded in your program. Something like:
InputStream is;
if (args.length > 0) {
is = new BufferedInputStream(
new FileInputStream(args[0]));
} else {
// No argument provided, so use program's default level data.
is = ClassLoader.getSystemClassLoader().getResourceAsStream("defaultlevel.txt");
}
chosenLevels = level.makeLevel(is);
¹ You may find some pages that claim you can determine the location of a running program’s code using getProtectionDomain().getCodeSource(), but getCodeSource() may return null, depending on the JVM and ClassLoader implementation, so this is not reliable.
To answer your first question, it doesn't seem like they're asking you to read from anywhere on disk, just from within your class path. So that seems fine.
The second question, "What does is mean 'should be hard-coded in your code, and be relative to the classpath'?". You are always going to have a default level file in your project directory. Define the path to this file as a String in your program and that requirement will be satisfied. It's related to the InputStream because the stream requires a location to read in from.

How & What does the delete method for a file actually delete?

Suppose I create a txt file and save it as "Untitled1". I enter eclipse and type the following:
import java.io.*;
public class Test {
public static void main(String[] args){
File f = new File("Untitled1.txt");
boolean isDeleted = f.delete();
System.out.println(isDeleted);
}
}
False was returned from the delete method indicating the file was not deleted. I understand that a file object represents the location of a file and NOT the contents of the file. But then what is actually being deleted? How do you delete a location of a file, without deleting the contents of a file itself?
I also entered the file Path for the Untitled1 file as a parameter to the File objects constructor, that did not delete the Untitled1.txt file either.
A file is identified by its path through the file system, beginning from the root node.
Representation of the path depends on the system. e.g. in windows C:\foo\bar while in linux /home/foo/bar.
So in below code, string path would be converted into abstract pathname and it would create the File instance and when you call the delete method it will try to delete the node. Basically content and path are not really different.
File f = new File("Untitled1.txt");
So, the file itself is deleted. False could be returned for a variety of reasons.
public boolean delete()
Deletes the file or directory denoted by this abstract pathname. If this pathname denotes a directory, then the directory must be empty in order to be deleted.
Note that the Files class defines the delete method to throw an IOException when a file cannot be deleted. This is useful for error reporting and to diagnose why a file cannot be deleted.
Returns:
true if and only if the file or directory is successfully deleted; false otherwise
Throws:
SecurityException - If a security manager exists and its SecurityManager.checkDelete(java.lang.String) method denies delete access to the file
Catch the SecurityException and you will probably find that you are disallowed from directly deleting the file programmatically.
First, please note that File is an old, bad class, that should not be used nowadays.
It's a lot better to use the Files class, more specifically its delete method.
As for what exactly is deleted: a file is a bunch of bytes that sits in a hard disk. The disk - or one of its partitions - is formatted into a filesystem, which is a data structure that organizes directories and files. The particular filesystem dictates how the file is broken up into pieces, how these pieces can be located or added by operations such as seek, read, write etc.
A filesystem has directories, which give you start points for the files. The file path in the hierarchy of directories tells the system where to find the file, including all its information (like pointer to its start, read/write permissions, etc.) The information in the directory that tells where the actual file contents is is sometimes called a "link" (at least in Unix file systems).
When you delete a file, the usual thing that happens is that the particular link to that file from that directory is removed. If that is the last link (the file can be linked from more than one directory, at least in some file systems), the blocks that belong to the file are also marked as free so that they can be allocated to another file.
So your File object tells the system where the file is, but the delete operation ultimately tells the system both to unlink the file from the directory (the penultimate part of the path), and if that's the last link, it also tells the system to go to the file contents and mark it as free.
This is a general description. The exact details and what happens when the content is marked as free is dependent on the particular filesystem used (e.g. ext4,reiserFS... (Linux), HFS+ (MacOS X), NTFS,FAT32... (Windows)).

Android get file using path (in String format)

My app needs to get an existing file for processing. Now I have the path of the file in String format, how can I get the File with it? Is it correct to do this:
File fileToSave = new File(dirOfTheFile);
Here dirOfTheFile is the path of the file. If I implement it in this way, will I get the existing file or the system will create another file for me?
That's what you want to do. If the file exists you'll get it. Otherwise you'll create it. You can check whether the file exists by calling fileToSave.exists() on it and act appropriately if it does not.
The new keyword is creating a File object in code, not necessarily a new file on the device.
I would caution you to not use hardcoded paths if you are for dirOfFile. For example, if you're accessing external storage, call Environment.getExternalStorageDirectory() instead of hardcoding /sdcard.
The File object is just a reference to a file (a wrapper around the path of the file); creating a new File object does not actually create or read the file; to do that, use FileInputStream to read, FileOutputStream to write, or the various File helper methods (like exists(), createNewFile(), etc.) for example to actually perform operations on the path in question. Note that, as others have pointed out, you should use one of the utilities provided by the system to locate directories on the internal or external storage, depending on where you want your files.
try this..
File fileToSave = new File(dirOfTheFile);
if(fileToSave.exists())
{
// the file exists. use it
} else {
// create file here
}
if parent folder is not there you may have to call fileToSave.getParentFile().mkdirs() to create parent folders

How to create a Path and a File that does not Exist in Java

This is the problem I have: If part or all of the path does not already exist, the server should create additional directories as necessary in the hierarchy and then create a new file as above.
Files.createDirectories(path);
That's what I am currently using, but it does not create the end file. For example is the path="/hello/test.html" it will create a directory called "hello" and one called "test.html", I want the test.html to be a file. How can I do that?
This is what I did to solve this "problem" or misuse of the libraries.
Files.createDirectories(path.getParent());
Files.createFile(path);
The first line will get the parent directory, so lets say this is what I want to create "/a/b/c/hello.txt", the parent directory will be "/a/b/c/".
The second like will create the file within that directory.
Have you looked at the javadoc? createDirectories only creates... directories. If you're intent on using Files.createDirectories, parse off the file name, call createDirectories passing only the path portion, then create a new file passing the entire path. Otherwise this is a better approach.
Files.createDirectories(path.substring(0, path.lastIndexOf(File.separator)+1));
File yourFile = new File(path);
you can parse the 'path' variable to isolate the file and the directory using delimiter as '/', and do File file = new File(parsedPath); This would work only when you know that you ALWAYS pass the file name at the end of it.
If you know when you are a) creating a directory b) creating a directory and file, you can pass the boolean variable that would describe if file needs to be created or not.

Does creation of new File(filename) object associate a process file descriptor with the object?

Does the following statement:
new File(filename);
associate a process file descriptor with the File object? Tried to search the same but without any success.
Ideally, it should not statically associate the file descriptor with the File object. Whenever, function calls are executed a file descriptor should get associated with the File Object for the period of time when the function call gets executed.
Any help appreciated.
There's no file descriptor, because new File(filename) does not open the file. It's just a easily manipulable representation of a path name.
File descriptors refer to open files. The fact that the file is not opened is not explicitly documented, but it follows from the principle of least surprise and from the fact that no exceptions are listed corresponding to failure to open the file.
No, new File(...) only is an object representing the filename, without even checking that there exists a file (or directory) with this name and/or path.
No. You can see this by examining the source of the File class yourself, from jdk 1.6.0_22:
public File(String pathname) {
if (pathname == null) {
throw new NullPointerException();
}
this.path = fs.normalize(pathname);
this.prefixLength = fs.prefixLength(this.path);
}
Since you can call the File constructor with a path that doesn't yet exist, and since File objects can represent non-existent Files, it wouldn't be possible to associate descriptors with it.

Categories