Do I need to close a FileOutputStream in the following example? And why?
FileOutputStream fos = new FileOutputStream("bytes.info");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(data);
oos.close();
If there were no exceptions thrown, then the FileOutputStream would be closed by ooo.close().
An exception thrown in writeObject would prevent any of the streams from being closed. So the close call should be in a finally block.
There's the additional problem that the ObjectOutputStream could throw an exception in its constructor. It writes the stream header in the constructor which can cause an exception. In this case, the FileOutputStream needs to be closed, but calling oos.close() is not possible because there's no reference to the ObjectOutputStream. So you really need two separate calls to close, one for each stream, both in finally blocks.
Using try-with-resources takes care of all of this for you:
try(
FileOutputStream fos = new FileOutputStream("bytes.info");
ObjectOutputStream oos = new ObjectOutputStream(fos)
) {
oos.writeObject(data);
}
Yes, you need to close the stream. Leaving FileOutputStream unclosed creates a possibility that some data that has been successfully written to the stream does not get saved to the file. If a program opens multiple file streams, not closing them creates a possibility of failures due to running out of native resources (too many files opened simultaneously).
FileOutputStream manages native resources, which are released by the close method. The class has a finalizer, too, which releases resources as well. As part of releasing native resources, the stream finishes out the writing of buffered data, if there is any. However, since JVM does not guarantee that a finalizer is going to be called on every object, failure to call close creates a risk of leaving buffered data unwritten.
Of course you have to close the FileOutputStream file. If not sometimes the data you save into the file might not get saved and you will end up with an empty file after executing the program. And you might wanna use try with resources so you won't have to close it manually and can do the exception handling part both at once.
try (FileOutputStream fos = new FileOutputStream("bytes.info");
ObjectOutputStream oos = new ObjectOutputStream(fos));{
}catch(){}
Just in case if you are not using try with resources close the file streams in the finally block manually.
FileOutputStream fos = null;
ObjectOutputStream oos = null;
try{
fos = new FileOutputStream("bytes.info");
oos = new ObjectOutputStream(fos));
oos.writeObject(data);
}catch(){
}finally{
if(fos != null){
fos.close();
}
if(oos != null){
oos.close();
}
}
It is a must to check whether those file streams are null or not. Because if they are null then there will be another error. Still it's better to use try with resources.
Related
I'm using the following code to write files to the disk.
`try{
FileOutputStream fileOutputStream = null;
fileOutputStream = new FileOutputStream(filePath);
fileOutputStream.write(fileData);
fileOutputStream.flush();
}
finally{
fileOutputStream.close();
}
`
The problem is that I'm getting the following error intermittently:
Insufficient system resources exist to complete the requested service.
I have already checked a few cases when this problem can happen, like the lack of Paged Pool Memory, but none of them is my case. I'm using windows server 2003 Server R2 SP2. Architecture x86.
Should I try to write the file in smaller chunks? What is the best way to do that?
A few things.
First, you should consider using buffers. Try wrapping your FileOutputStream with a BufferedOutputStream.
try{
BufferedOutputStream outputBuffer = null;
outputBuffer = new BufferedOutputStream (new FileOutputStream(filePath));
outputBuffer.write(fileData);
outputBuffer.flush();
}
finally{
outputBuffer.close();
}
Second, try checking if you really are running out of handles. I left a comment with a link regarding this.
If I create my BufferedInputStream via…
FileInputStream fos = new FileInputStream(FILE_TO_READ);
BufferedInputSteam bos new BufferedInputSteam(fos);
…
bos.close();
fos.close();
I can close the FileInputStream explicitly. But if I create it nested…
BufferedInputSteam bos new BufferedInputSteam(new FileInputStream(FILE_TO_READ));
…
bos.close();
I can not close the FileInputStream explicitly.
Is this a memory leak?
I don't believe so. According to the Java Documention found here
Closes this file input stream and releases any system resources associated with the stream.
If this stream has an associated channel then the channel is closed as well.
InputStream classes are based on the Decorator Pattern so no memory issue, it will be properly closed.
You just have to close the top level InputStream
bos.close();
You can't close the underlying input stream, because the BufferedInputSteam closes it for you. It's meant to be a convenience and it's only reasonable. Think about it, *why should you be allowed access to the underlying FileInputStream, independently of the BufferedInputSteam that encapsulates it? Such access will likely allow you to break the BufferedInputSteam.
Trying to close an already closed stream will give you an IOException: Stream already closed exception anyway
My code like below.
Map<String, String> aMap = new HashMap();
aMap.put("A", "a");
FileOutputStream fos = new FileOutputStream(new File("some.txt"));
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.write(aMap);
oos.flush();
oos.close();
I thought I need to close fos, but other says its fine.
Is it really fine to not close FileOutputStream, because I already closed inner OutputStream?
Yes, You don't need to close it separately. If you close your oos, it will internally close fos as well. Closing the outer most stream will delegate it all the way down
No you dont need to close FileOutputStream.
If you check the code of close() you will found that it closes the output stream.
Plz see the doc http://docs.oracle.com/javase/7/docs/api/java/io/ObjectOutputStream.html
You don't need to do this explicitly, it will be done automatically. Take a look at the example from javadoc:
FileOutputStream fos = new FileOutputStream("t.tmp");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeInt(12345);
oos.writeObject("Today");
oos.writeObject(new Date());
oos.close();
The link could be found here: Class ObjectOutputStream
It's a general rule in Java: if you have several chained/nested streams say
outStream3(outStream2(outStream1)) (I am writing this just in pseudo-code) you
usually need to close only the outermost stream - i.e. outStream3 in this case.
Internally when you call close on outStream3, it will call close on outStream2
which will call close on outStream1. There are a few exceptions to this rule, but
this is the general rule you can remember.
I want to be able to read an object from a file after I streamed one out to it.
Now, It works fine when I am reading at the first time, but when I'm trying to read again (to another object), there is an exception I'm unable to handle.
Now, I'm guessing the file index got to the end of the file, therefore I cannot read again from it.
Am I wrong? If not, can I set the file index to the start of the file?
try{
Classba cb=new Classba();
FileOutputStream fos=new FileOutputStream(args[0]);
ObjectOutputStream oos=new ObjectOutputStream(fos);
oos.writeObject(cb);
FileInputStream fis=new FileInputStream(args[0]);
ObjectInputStream ois=new ObjectInputStream(fis);
Classba cb2;
cb2=(Classba)ois.readObject();
cb2.print();
Classba cb3; //*OK Till Here*//
cb3=(Classba)ois.readObject();
}
You can call the method reset() on your ObjectInputStream.
I have application (Java5) distributed among several JVMs that reads/writes files from a shared storage (the storage is managed by Windows). I wanted to use exclusive/shared locks for file write/read as following:
FileOutputStream fos = null;
FileLock lock = null;
ObjectOutputStream oos = null;
try {
fos = new FileOutputStream(new File("//share/test.dat")); // HERE IT MAY THROW FileNotFoundException...
lock = fos.getChannel().lock(); // ... and I won't acquire a lock.
oos = new ObjectOutputStream(fos);
oos.writeObject(value);
return true;
} catch (Exception e) {
// Log it.
} finally {
// Close locks and I/O streams.
}
The problem: if JVM1 is currently reading the file test.dat and JVM2 is trying to write to the same file then FileNotFoundException ("The process cannot access the file because it is being used by another process") will be thrown on JVM2 in "new FileOutputStream(new File("//share/test.dat"))" line.
It seems to be Catch22 case: on the one hand I want to acquire a lock to get I/O stream; on the other hand I need to have an I/O stream to acquire a lock.
As I could see, the same situation with RandomAccessFile.
Any ideas?..
As you can see from the error message, Windows just won't let you do what you're trying to do. You can treat the Windows error itself as the lock condition, if you think about it. You would have a cognate problem here anyway because of the timing window between the open and the lock. Windows in a way is doing you a favor here. For once.