Why doesn't java.io.File have a close method? - java

While java.io.RandomAccessFile does have a close() method java.io.File doesn't. Why is that? Is the file closed automatically on finalization or something?

The javadoc of the File class describes the class as:
An abstract representation of file and directory pathnames.
File is only a representation of a pathname, with a few methods concerning the filesystem (like exists()) and directory handling but actual streaming input and output is done elsewhere. Streams can be opened and closed, files cannot.
(My personal opinion is that it's rather unfortunate that Sun then went on to create RandomAccessFile, causing much confusion with its inconsistent naming.)

java.io.File doesn't represent an open file, it represents a path in the filesystem. Therefore having close method on it doesn't make sense.
Actually, this class was misnamed by the library authors, it should be called something like Path.

Essentially random access file wraps input and output streams in order to manage the random access. You don't open and close a file, you open and close streams to a file.

A BufferedReader can be opened and closed but a File is never opened, it just represents a path in the filesystem.

Say suppose, you have
File f = new File("SomeFile");
f.length();
You need not close the Files, because its just the representation of a path.
You should always consider to close only reader/writers and in fact streams.

As already stated, the File class does not have a closing method as it's merely a path or a reference to the actual File.
You will usually use this File class as a helper to open the actual file with a FileReader class which you can close. That said, it does close itself on exit but if you read a file from your program and then try to do something to this file externally, it could result in an error on that external call, so it's better to close it
File path = new File(/some/path/file.txt);
FileReader actualFile = new FileReader(path);
...<
if(imDoneWithTheFile)
actualFile.close();

Related

Does RandomAccessFile create a new file, if the specidied one does not exist? Does it replace the file with a new one if it does exist?

I've already created a method that uses createNewFile to create a new file and it does so successfully. I've also made a method that's supposed to open files, using randomAccessFile. Due to some issues I checked to see whether a new file is created if I put a new name as a parameter in randomAccessfile and it is. I was wondering if that's actually the case and if so, what can I replace it with in order to open files and read-write on them. I can't change much to the "general idea" of my program since this is a part of an assignment.
The documentation of the RandomAccessFile states about the mode parameter to the class's two constructors:
"r" Open for reading only. Invoking any of the write methods of the
resulting object will cause an IOException to be thrown.
"rw" Open for reading and writing. If the file does not already exist then an
attempt will be made to create it.
The file is only created or modified if you supply a "w" in to the file mode. The file will be created if it doesn't exist, but the contents will not be changed if the file does exist because you are opening the file for both reading and writing.
There is no write mode that causes a file to be opened only if it exists, failing otherwise. To get that functionality in your code, you'd want to first check for the existence of the file, and have your logic do whatever is appropriate when the file does not exist.

Writing to a text file within a jar file

I was recently trying to export my game to a jar file, and I ran into a problem with converting files to input and output streams. With the regular code that was not exported, I was able to read and write to text files by simply calling the Scanner and PrintStream constructor with the File location. This didn't work inside the jar because apparently these were no longer considered as files. I was able to work around the input stream one by doing this:
Scanner infile = new Scanner(this.getClass().getResourceAsStream("Resources/leaderboard.txt"));
as opposed to,
Scanner infile = new Scanner("Resources/leaderboard.txt");
And I am trying to utilize PrintStream, but so far I have not found an equivalent function that will take in a String location and return an OutputStream for the PrintStream constructor. Should I use a different method for writing to text files in a jar, is there a function or method of converting it to an OutputStream that I have yet to see, or should I avoid printing to a text file altogether?
Thanks in advance.
You shouldn't and for practical purposes can't write to a "file" within a jar file. Yes, there are kludges that allow you to get around this, but they shouldn't be implemented. Instead all files that the program might change should be outside of the jar and should be separate files.

Reading all object files in directory with single stream

If I had a directory filled with different object files, is there a way I could input them into my application without opening a new stream every time? I am currently using ObjectInputStream, but I don't mind using another form of IO.
For example, if I stored my users directly onto my harddrive as objects (each having their own file: name.user), is there a way I could load them all back in using the same stream? Or would it be impossible seeing how a new File object would be needed for each individual file? Is there a way around this?
Each file will need its own stream behind the scenes; there's no way round that. But that doesn't stop you creating your own InputStream that manages this for you, and then allows you to read everything off from one stream.
The idea would be that when you try to read from your CompoundObjectInputStream or whatever, it looks to see if there are any more files that it hasn't yet processed, and opens one if so using another stream, and passes the data through. When it reaches the point where there are no more files in that directory, the CompoundObjectInputStream indicates end-of-stream.
No, there is not. Each physical file requires its own FileInputStream, FileChannel, or other corresponding native accessor.
Note that File has no direct link to a physical file, it is just an abstract path name.

Is there an easy way to create a Java InputStream that consists of several appended files?

I have a "processor" component that can process a single File, InputStream, Reader, or etc.
For various reasons, I end up with several large files instead of one huge file.
Is there a way to construct an input stream (or reader) that: transparently "appends" all these files so that:
1) The "processor" does not know where one file started or another ended
2) No changes occur in the file system (e.g., no actual appending of files)
3) Each file is read in order so that I do not pay the cost of loading all of them to memory and appending them before the processor starts reading?
I'm sure it is possible to write something like this, but I'm wondering if one exists already; it's been a while since I did file based IO.
SequenceInputStream concatenates multiple streams.
List<InputStream> opened = new ArrayList<InputStream>(files.size());
for (File f : files)
opened.add(new FileInputStream(f));
InputStream is = new SequenceInputStream(Collections.enumeration(opened));
Exception handling (not shown) when opening each file is important; be certain that all files are certain to be closed eventually, even if the operation is aborted before the SequenceInputStream is created.
You can use something like SequenceInputStream to read one stream after the other.

Can I write to the end of a 5GB file in Java?

Can I write to the end of a 5GB file in Java? This question came up in my office and no one is sure what the answer is.
This should be possible fairly easily using a RandomAccessFile. Something like the following should work:
String filename;
RandomAccessFile myFile = new RandomAccessFile(filename, "rw");
// Set write pointer to the end of the file
myFile.seek(myFile.length());
// Write to end of file here
Yes. Take a look at this link RandomAccessFile
http://java.sun.com/javase/6/docs/api/java/io/RandomAccessFile.html#seek(long)
That is , you open the file, and then set the position to the end of the file. And start writing from there.
Tell us how it went.
Actually that would depend on the underlying File System and how the JVM on that platform implements the File Stream. Because, if a file is bigger than 5GB you cannot, with a 32Bit operative system open the whole file and just write to it, because of the 4.3 Billion limit stuff ( 32^2 ).
So, the answer shortly would be, Yes, it is possible, IF Java handles the file correctly and the File System is a good one :)
If you just mean that you need to append to the file, check out the
FileWriter(File file, boolean append)
constructor in the FileWriter class.
Sorry, I don't have a 5GB file handy to test with. :)
5GB? I wonder if the OS is a bigger problem, but that's doubtful.
In theory, you can just open the file in append mode.
OutputStream in = new java.io.FileOutputStream(fileName, true);
and write till the filesystem fills up.
See Bill the Lizard for char data.

Categories