Return in a 'finally' statement - java

I'm trying to read ObjectOutputStream from a file and convert it to an arraylist.
This whole thing is happening inside a method which should read the file and return the array list:
public static List<Building> readFromDatabase(){
String fileName="database.txt";
FileInputStream fileIStream=null;
ObjectInputStream in=null;
List<Building> buildingsArr=null;
try
{
fileIStream = new FileInputStream(fileName);
in = new ObjectInputStream(fileIStream);
buildingsArr=(ArrayList<Building>)in.readObject();
}
catch(IOException e)
{
e.printStackTrace();
}
catch(ClassNotFoundException e)
{
Console.printPrompt("ArrayList<Building> class not found.");
e.printStackTrace();
}
finally{
Console.printPrompt("Closing file...");
close(in);
close(fileIStream);
return buildingsArr;
}
}
Java tells me that this is dangerous.
What are the alternatives?
I can't put the return in the "try" block because it won't do it / it won't close files in the "finally" block.
I need to both make sure files will be closed, and return the array list I created as well.
Any ideas?

I can't put the return in the "try" block because it won't do it / it
won't close files in the "finally" block.
Wrong, finally block would still execute if you put return in try block. Thus you can return in your try block.
try
{
//your code
return buildingsArr;
}
catch(IOException e)
{
e.printStackTrace();
}
catch(ClassNotFoundException e)
{
Console.printPrompt("ArrayList<Building> class not found.");
e.printStackTrace();
}
finally{
Console.printPrompt("Closing file...");
close(in);
close(fileIStream);
}

I would suggest starting to use Java 7, and the try with resources clause. http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
Ex:
static String readFirstLineFromFile(String path) throws IOException {
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
return br.readLine();
}
}

You must either throw an Exception or return a value:
All you need to prove this is comment out the return "File Not Found" after the finally block and see that it won't compile.
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
public class ReturnFinallyExample
{
public static void main(final String[] args)
{
returnFinally();
}
private static String returnFinally()
{
try
{
final File f = new File("that_does_not_exist!");
final FileInputStream fis = new FileInputStream(f);
return "File Found!";
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
finally
{
System.out.println("finally!");
}
return "File Not Found!";
}
}
You must have the return after the finally or you have to either:
declare the method to throws FileNotFoundExceptoin and re-throw the FileNotException out.
or
wrap the FileNotFoundException with throw new RuntimeException(e)

Related

How to prevent the block from being displayed, finally, if there is no path to the file

Problem: if the path to the file was not specified in the arguments, then it still displays the phrase "The file was closed". This works 2 times. In uploadToFile and read method. I pass one path in the arguments, and the second is written in the DownloadFile
public class Task implements AutoCloseable {
public static void main(String[] args) throws IOException {
String DownloadFile = "C:\\Users\\VGilenko\\IdeaProjects\\Task\\src\\main\\resources\\Out.txt";
Map<String, Departament> departments = new HashMap<>();
String path = args.length > 0 ? args[0] : null;
read(path, departments);
transferToDepartment(departments, DownloadFile);
}
private static void uploadToFile(List download, String path) {
int i = 0;
try (FileWriter writer = new FileWriter(path, false)) {
...
}
} catch (IOException ex) {
System.out.println(ex.getMessage());
} finally {
System.out.println("The file was closed");
}
}
public static void transferToDepartment(Map<String, Departament> departments, String downloadFile) {
List<String> download = new ArrayList<>();
...
}
uploadToFile(download, downloadFile);
}
public static void read(String path, Map<String, Departament> departments) throws IOException {
assert path != null;
try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(path), "CP1251")); br) {
.....
}
}
} catch (FileNotFoundException e) {
System.out.println("The file was not found, check the path");
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Correct the file path, step out of the array");
} catch (NullPointerException e) {
System.out.println("You forgot to register the path to the file");
} finally {
System.out.println("The file was closed");
}
}
#Override
public void close() {
System.out.println("The file was closed");
}
}
You have your printout "The file was closed" in your finally statement. If you don't specify a file, you will catch an Exception, and your finally block will be executed.
An easy fix would be to check for the existence of the path (not being empty, not being null).

Eclipse Juno : unassigned closeable value

I am wondering why I get this warning with the new eclipse Juno despite I think I correctly closed everything. Could you please tell me why I get this warning in the following piece of code?
public static boolean copyFile(String fileSource, String fileDestination)
{
try
{
// Create channel on the source (the line below generates a warning unassigned closeable value)
FileChannel srcChannel = new FileInputStream(fileSource).getChannel();
// Create channel on the destination (the line below generates a warning unassigned closeable value)
FileChannel dstChannel = new FileOutputStream(fileDestination).getChannel();
// Copy file contents from source to destination
dstChannel.transferFrom(srcChannel, 0, srcChannel.size());
// Close the channels
srcChannel.close();
dstChannel.close();
return true;
}
catch (IOException e)
{
return false;
}
}
IF you're running on Java 7, you can use the new try-with-resources blocks like so, and your streams will be automatically closed:
public static boolean copyFile(String fileSource, String fileDestination)
{
try(
FileInputStream srcStream = new FileInputStream(fileSource);
FileOutputStream dstStream = new FileOutputStream(fileDestination) )
{
dstStream.getChannel().transferFrom(srcStream.getChannel(), 0, srcStream.getChannel().size());
return true;
}
catch (IOException e)
{
return false;
}
}
You won't need to explicitly close the underlying channels. However if you're not using Java 7, you should write the code in a cumbersome old way, with finally blocks:
public static boolean copyFile(String fileSource, String fileDestination)
{
FileInputStream srcStream=null;
FileOutputStream dstStream=null;
try {
srcStream = new FileInputStream(fileSource);
dstStream = new FileOutputStream(fileDestination)
dstStream.getChannel().transferFrom(srcStream.getChannel(), 0, srcStream.getChannel().size());
return true;
}
catch (IOException e)
{
return false;
} finally {
try { srcStream.close(); } catch (Exception e) {}
try { dstStream.close(); } catch (Exception e) {}
}
}
See how much better the Java 7 version is :)
You should always close in finally because if an exception rise, you won't close the resources.
FileChannel srcChannel = null
try {
srcChannel = xxx;
} finally {
if (srcChannel != null) {
srcChannel.close();
}
}
Note: even if you put a return in the catch block, the finally block will be done.
eclipse is warning you about the FileInputStream and FileOutputStream that you can no longer reference.

do I need to surround fileInputStream.close with a try/catch/finally block? How is it done?

I have the following Java Class that does one thing, fires out values from config.properties.
When it comes time to close the fileInputStream, I think I read on Wikipedia that it is good to have it in a finally block. Because it honestly works just fine in try/catch block.
Can you show me correction to get fileInputStream.close() in a finally section?
ConfigProperties.java
package base;
import java.io.FileInputStream;
import java.util.Properties;
public class ConfigProperties {
public FileInputStream fileInputStream;
public String property;
public String getConfigProperties(String strProperty) {
Properties configProperties = new Properties();
try {
fileInputStream = new FileInputStream("resources/config.properties");
configProperties.load(fileInputStream);
property = configProperties.getProperty(strProperty);
System.out.println("getConfigProperties(" + strProperty + ")");
// use a finally block to close your Stream.
// If an exception occurs, do you want the application to shut down?
} catch (Exception ex) {
// TODO
System.out.println("Exception: " + ex);
}
finally {
fileInputStream.close();
}
return property;
}
}
Is the solution only to do as Eclipse suggests and do this in the finally block?
finally {
try {
fileInputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Yes, that is the common pre-Java 7 solution. However, with the introduction of Java 7, there are now try-with-resource statements which will automatically close any declared resources when the try block exits:
try (FileInputStream fileIn = ...) {
// do something
} // fileIn is closed
catch (IOException e) {
//handle exception
}
The standard approach is:
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream(...);
// do something with the inputstream
} catch (IOException e) {
// handle an exception
} finally { // finally blocks are guaranteed to be executed
// close() can throw an IOException too, so we got to wrap that too
try {
if (fileInputStream != null) {
fileInputStream.close();
}
} catch (IOException e) {
// handle an exception, or often we just ignore it
}
}
Because FileInputStream.close() throws an IOException, and the finally{} block doesn't catch exceptions. So you need to either catch it or declare it in order to compile. Eclipse's suggestion is fine; catch the IOException inside the finally{} block.
It's a good habit to close streams because what it does in background it's called buffering, meaning that it does not free the internal buffer and does not free the file descriptor.

EOFException in Java Android? Help needed

I am trying to do some kind of serialization where I can directly read and write objects from file.
To start of I just tried to write a character to file and tried to read it. This keeps giving me EOF exception always.
I am trying it on a Android device. Here is my code:
public class TestAppActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
try {
WriteToFile();
Load();
} catch (Exception e) {
e.printStackTrace();
}
}
public void Load () throws IOException
{
InputStream fis;
ObjectInputStream in = null;
try {
fis = new FileInputStream(Environment.getExternalStorageDirectory() + "\\test2.ser");
in = new ObjectInputStream(fis);
char temp = in.readChar();
} catch (IOException e) {
e.printStackTrace();
} finally {
in.close();
}
}
public static void WriteToFile() throws Exception {
try {
OutputStream file = new FileOutputStream(Environment.getExternalStorageDirectory() + "\\test2.ser");
ObjectOutput output = new ObjectOutputStream(file);
try {
output.writeChar('c');
} finally {
output.close();
}
} catch (IOException ex) {
throw ex;
}catch (Exception ex) {
throw ex;
}
}
}
In this case, EOFException means there is no more data to be read, which (again in this case) can only mean that the file is empty.
Why are you using ObjectInput/OutputStreams but only writing chars? You'd be better off with DataInput/OutputStreams for that usage.
Also there is no point in catching exceptions only to rethrow them.
Also there is no point in reading a char from a file unless you are going to put it somewhere other than in a local variable that isn't even returned by the method.
I have imported this code in my sample project with following change.
i replaced "\\test2.ser"with "/test2.ser" and it worked. please try this.

Is it okay to use try catch inside finally?

I am using a buffered writer and my code, closes the writer in the finally block. My code is like this.
...........
BufferedWriter theBufferedWriter = null;
try{
theBufferedWriter =.....
....
......
.....
} catch (IOException anException) {
....
} finally {
try {
theBufferedWriter.close();
} catch (IOException anException) {
anException.printStackTrace();
}
}
I have to use the try catch inside the clean up code in finally as theBufferedWriter might also throw an IOException. I do not want to throw this exception to the calling methos. Is it a good practice to use a try catch in finally? If not what is the alternative? Please suggest.
Regards,
Hiral
A somewhat nicer way to do this is to use IOUtils.closeQuiety from Apache commons-io. It keeps your code tidy and eliminates some of the boilerplate that's inherent in Java.
You code then becomes:
BufferedWriter theBufferedWriter = null;
try{
theBufferedWriter = ...
...
} catch (IOException anException) {
...
} finally {
IOUtils.closeQuietly(theBufferedWriter);
}
Much nicer and more expressive.
In pre Java 7, I'd say what you have written is the best solution.
In Java 7 and onwards you have Automatic Resource Management intended to simplify these things. With this feature, you can do
BufferedWriter theBufferedWriter = null;
try (BufferedWriter theBufferedWriter = ...) {
....
......
.....
} catch (IOException anException) {
....
}
Or you can use Lombok and the #Cleanup annotation and you shall never write a try catch inside finally again.
This is how you would normally write it (Note the throws IOException):
//Vanilly Java
import java.io.*;
public class CleanupExample {
public static void main(String[] args) throws IOException {
InputStream in = new FileInputStream(args[0]);
try {
OutputStream out = new FileOutputStream(args[1]);
try {
byte[] b = new byte[10000];
while (true) {
int r = in.read(b);
if (r == -1) break;
out.write(b, 0, r);
}
} finally {
out.close();
}
} finally {
in.close();
}
}
}
Now with Lombok you just write #Cleanup on the streams
import lombok.Cleanup;
import java.io.*;
public class CleanupExample {
public static void main(String[] args) throws IOException {
#Cleanup InputStream in = new FileInputStream(args[0]);
#Cleanup OutputStream out = new FileOutputStream(args[1]);
byte[] b = new byte[10000];
while (true) {
int r = in.read(b);
if (r == -1) break;
out.write(b, 0, r);
}
}
}
This is what we will have to live with until Java 7 and ARM Blocks.
It's OK but you should test if theBufferedWriter is not null before closing it.
You could also do:
BufferedWriter theBufferedWriter;
try {
theBufferedWriter = new ...
try {
...
} finally {
try {
theBufferedWriter.close();
} catch (IOException closeException) {
closeException.printStackTrace();
}
}
} catch (IOException anException) {
...
}
or:
BufferedWriter theBufferedWriter;
try {
theBufferedWriter = new ...
} catch (IOException createException) {
// do something with createException
return; // assuming we are in a method returning void
}
try {
...
} catch (IOException anException) {
...
// assuming we don't return here
}
try {
theBufferedWriter.close();
} catch (IOException closeException) {
closeException.printStackTrace();
}
but mostly I do such operations (e.g. writing a file) in a dedicated method and prefer to throw the/an Exception so the caller can handle it (e.g. asking for another file, stopping the application, ...):
void someMethod(...) throws IOException {
BufferedWriter theBufferedWriter = new ...
try {
...
} catch (IOExcepption anException) {
try {
theBufferedWriter.close();
} catch (IOException closeException) {
closeException.printStackTrace();
// closeException is not thrown, anException represents the main/first problem
}
throw anException;
}
theBufferedWriter.close(); // throws the Exception, if any
}
Please note: English is not my first nor my second language, any help would be appreciated
It's ok to put a try-catch in a finally. It is the tool that does what you want to do. However, I feel the thrown IOException on close is uncommon enough that I would allow it to suppress any exception in the body like so.
try {
BufferedWriter writer = .....
try {
.....
} finally {
writer.close();
}
} catch (IOException e) {
....
}

Categories

Resources