Which would be considered more proper technique for implementing a try/catch in Java:
A:
Date lastMod = null;
BufferedReader inFile = null;
try {
inFile = new BufferedReader(new FileReader("C:\\Java\\settings.ini"));
try {
lastMod = new Date(Long.parseLong(inFile.readLine()));
} catch (IOException e) {
e.printStackTrace();
}
} catch(FileNotFoundException e) {
e.printStackTrace();
}
or B:
Date lastMod = null;
BufferedReader inFile = null;
try {
inFile = new BufferedReader(new FileReader("C:\\Java\\settings.ini"));
lastMod = new Date(Long.parseLong(inFile.readLine()));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Also, is it wrong to follow the try/catch block with a long block of code that makes use of the BufferedReader, or is it preferred to include the long block of code inside the try/catch?
For example:
public static void main(String[] args) {
Date lastMod = null;
BufferedReader inFile = null;
try {
inFile = new BufferedReader(new FileReader("C:\\Java\\settings.ini"));
lastMod = new Date(Long.parseLong(inFile.readLine()));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
//Long block of code using inFile
inFile.readLine();
inFile.close();
Versus:
public static void main(String[] args) {
Date lastMod = null;
BufferedReader inFile = null;
try {
inFile = new BufferedReader(new FileReader("C:\\Java\\settings.ini"));
lastMod = new Date(Long.parseLong(inFile.readLine()));
//Long block of code using inFile
inFile.readLine();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
inFile.close();
}
B is much more readable, when there is nothing going on after the internal try block, before the external try block. If you have logic to perform in between, then you must use A
In the second example the second version using finally is critical to ensure that close will be called no matter what (even if the function returns first) The first version without finally is actually wrong, since you may use up all the file handles and be unable to open more files.
As an additional note, you may need to check for null when calling close. And if you are using java 7, it's even better to use "try with resources".
For the first question: the solution A add unnecessary complexity. Use B or, if you are using Java 7, try-with-resources:
Date lastMod = null;
try (BufferedReader inFile = new BufferedReader(new FileReader("C:\\Java\\settings.ini"))){
lastMod = new Date(Long.parseLong(inFile.readLine()));
} catch (FileNotFoundException | IOException e) {
e.printStackTrace();
}
For the second question: in the first version, what if the BufferedReader creation throws an exception? You would use brafter which is null and would throw a NullPointerException. Also if something else happen, you will not have called inFile.close(), so you really need a finally. For all these reasons, again, the second solution is better.
If you are using try-with-resouces (Java 7), of course, you don't need a finally block to release your BufferedReader.
Proper technique might also include not catching your exceptions, but allowing them to bubble up to a caller instead. Do always use a finally block to clean up any state that might otherwise use up resources, but you'll often be better off catching the exception in the parent routine rather than the child routine in which the exception was thrown.
In general, if it would be helpful to know in the calling routine whether the sub-routine succeeded or not, then that sub-routine should not catch its exceptions, but should allow them to bubble up to their caller.
Related
Good day,
Why in video lessons one human was not using try-catch, and, if i not be using try-catch i have an error IOException on createnewFile(), FileWriter etc.
Maybe this is easy, i from c++, its big question for me.
Thats my code:
PS. Sorry for "best english"
public static void main(String[] args) {
System.out.println("Hello World");
File file1 = new File("temp.txt");
if(!file1.exists()) {
System.out.println("Creating file...");
try
{
file1.createNewFile();
}
catch (IOException e)
{
e.printStackTrace();
}
}
try
{
FileWriter fw = new FileWriter(file1);
BufferedWriter out = new BufferedWriter(fw);
out.write("aString");
out.flush();
out.close();
FileReader fr = new FileReader(file1);
BufferedReader in = new BufferedReader(fr);
while(in.ready()) {
System.out.println(in.readLine());
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
We use try- catch block to maintain the flow of execution of code.
If exception occurs it goes to catch block and e.printStackTrace it gives us the information why exception occurs and we can handle it here with our logic.
if we dont use try-catch the flow of code is stuck where exception occurs.
So thats why we use try-catch block.
Java requires that you handle checked exceptions in your code, either by specifying that your method can throw the exception or by handling it with a try-catch block. If you don't do one of these two at the point where you call a method that may throw a checked exception such as IOException, the compiler is going to produce an error.
You can learn about exceptions in Java here: Lesson: Exceptions (Oracle Java Tutorials).
Specifically: The Catch or Specify Requirement
public void lock() {
if (this.isLocked()) return;
try {
this.dataOut.flush();
this.dataOut.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
DataInputStream inputStream =
new DataInputStream(
new BufferedInputStream(
new ByteArrayInputStream(
this.byteOut.toByteArray())));
IntStream.Builder intStreamBuilder = IntStream.builder();
try {
try {
while (true) {
intStreamBuilder.accept(inputStream.readInt());
}
} catch (EOFException e) {
// logic to be executed after stream has been fully read
int[] pool = intStreamBuilder.build().toArray();
super.lock(pool);
} finally {
inputStream.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
What I do here is take an DataOutputStream containing Integers, flush its remaining contents into a ByteArrayOutputStream named this.byteOut and then build an IntStream from it.
I'm from the C# domain and in the process of learning Java, so the code here does not have any actual purpose.
Is there any way to do what I do here more elegantly in Java?
My two main concerns are:
The way I determine that the DataInputStream has been fully read is by catching an EOFException and putting the logic to be executed after reading inside a catch block. I don't like that, since I suppose throwing and catching exceptions is somewhat expensive? Is there a better way to determine that the stream doesn't contain any more Integers?
The fact that I have to wrap a try-catch block around a try-catch block just to be able to call inputStream.close() in the inner finally block. Is there a solution that is not so clunky?
It's mostly you.
If you don't like the try with resources construct,
you can still combine all of your try statments and stack the catch blocks.
public void lock()
{
DataInputStream inputStream = null;
IntStream.Builder intStreamBuilder;
if (isLocked())
{
return;
}
try
{
inputStream = new DataInputStream(
new BufferedInputStream(
new ByteArrayInputStream(
byteOut.toByteArray())));
intStreamBuilder = IntStream.builder();
dataOut.flush();
dataOut.close();
while (true)
{
intStreamBuilder.accept(
inputStream.readInt());
}
}
catch (IOException exception)
{
throw new RuntimeException(exception);
}
catch (EOFException ignoredException)
{
// logic to be executed after stream has been fully read
int[] pool = intStreamBuilder.build().toArray();
super.lock(pool);
}
finally
{
if (inputSream != null)
{
try
{
inputStream.close();
}
catch (IOException exception)
{
throw new RuntimeException(exception);
}
}
}
}
The try inside the finally is required.
I prefer the try-with-resources construct.
If I were you I will change my code to be as the following
//try-with-resources-close
try (DataInputStream inputStream =
new DataInputStream(
new BufferedInputStream(
new ByteArrayInputStream(
this.byteOut.toByteArray())))) {
IntStream.Builder intStreamBuilder = IntStream.builder();
byte[] byts = new byte[4];
while (inputStream.read(byts) > -1) {// read 4 bytes and convert them to int
int result = ByteBuffer.wrap(byts).getInt();
intStreamBuilder.accept(result);
}
// logic to be executed after stream has been fully read
int[] pool = intStreamBuilder.build().toArray();
super.lock(pool);
} catch (IOException e) {
throw new RuntimeException(e);
}
try-with-resources this new way added in Java 7 to close any object that implements AutoCloseable automatically when try block is executed
readInt method it works as the following read 4 bteys then convert them to int
int ch1 = in.read();
int ch2 = in.read();
int ch3 = in.read();
int ch4 = in.read();
if ((ch1 | ch2 | ch3 | ch4) < 0)
throw new EOFException();
return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
//So you also can do the same thing, but instead of throws EOFException
you can add return false or break the loop
for read bytes method if no bytes existed then it reture -1
Well the better solution I found thanks to #Oliver Charlesworth is the following:
try (DataInputStream inputStream =
new DataInputStream(
new BufferedInputStream(
new ByteArrayInputStream(this.byteOut.toByteArray())))) {
while (true)
intStreamBuilder.accept(inputStream.readInt());
} catch (EOFException e) {
int[] pool = intStreamBuilder.build().toArray();
super.lock(pool);
} catch (IOException e) {
throw new RuntimeException(e);
}
This still has logic inside the catch block the code look definitely cleaner.
However, I cannot come up with a better approach that determines that the InputDataStream has been fully read.
What bugs me about this is that reaching the end of the stream is expected and it would actually be exceptional if no exception was thrown, what IMO defeats the purpose of exceptions in the first place.
I asked a separate question of the possible use of Java NIO's IntBuffer class here. My above snippet could be changed to:
IntBuffer intBuffer = ByteBuffer.wrap(this.byteOut.toByteArray()).asIntBuffer();
while (intBuffer.hasRemaining()){
intStreamBuilder.accept(intBuffer.get());
}
int[] pool = intStreamBuilder.build().toArray();
super.lock(pool);
Hi can we use both try with resources and multi-catch together in Java 7? I tried to use it and it gives compilation error. I may be using it wrongly. Please correct me.
try(GZIPInputStream gzip = new GZIPInputStream(new FileInputStream(f));
BufferedReader br = new BufferedReader(new InputStreamReader(gzip))
{
br.readLine();
}
catch (FileNotFoundException | IOException e) {
e.printStackTrace();
}
Thanks in advance.
Yes! you can.
But, your problem is in FileNotFoundException with IOException. Because FileNotFoundException is subclass of IOException, which is invalid. Use only IOException in catch block. You have also missing the one right parenthesis ) in try statement. Thats why, you got errors.
try(GZIPInputStream gzip = new GZIPInputStream(new FileInputStream(f));
BufferedReader br = new BufferedReader(new InputStreamReader(gzip)))
{
br.readLine();
}
catch (IOException e) {
e.printStackTrace();
}
This is very much possible in Java SE 7. A piece from the official Oracle Documentation :
The new syntax allows you to declare resources that are part of the try block. What this means is that you define the resources ahead of time and the runtime automatically closes those resources (if they are not already closed) after the execution of the try block.
public static void main(String[] args)
{
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(
new URL("http://www.yoursimpledate.server/").openStream())))
{
String line = reader.readLine();
SimpleDateFormat format = new SimpleDateFormat("MM/DD/YY");
Date date = format.parse(line);
} catch (ParseException | IOException exception) {
// handle I/O problems.
}
}
#Masud in right in saying the FileNotFoundException is a subclass of IOException, and that they cannot be used like
catch (FileNotFoundException | IOException e) {
e.printStackTrace();
}
But you certainly can do something like this:
try{
//call some methods that throw IOException's
}
catch (FileNotFoundException e){}
catch (IOException e){}
Here's a Java tip that is very useful : When catching exceptions, don't cast your net too wide.
Hope it helps. :)
I have run into quite a snag while writing my app. Here is my issue:
I am trying to initialize the file input stream like so:
FileInputStream fis
fis = openFileInput(selectedFile);
Then put this 1 line later:
byte[] input = new byte[fis.available()];
Problem is both bits of code need try/catch statements and the second block cannot recognize fis because it was initialized within a try/catch. Here is my code:
private void openFile(String selectedFile) {
String value = "";
FileInputStream fis;
try {
fis = openFileInput(selectedFile);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
try {
byte[] input = new byte[fis.available()];
} catch (IOException e) {
e.printStackTrace();
}
What should I do? (Thanks in advance)
The best approach in this situation is not to catch IOException at all.
private void openFile(String selectedFile) throws IOException {
FileInputStream fis = openFileInput(selectedFile);
byte[] input = new byte[fis.available()];
It does not make sense to continue after you got FileNotFoundException
Set FileInputStream fis = null; when you first declare the variable.
You could also run your code like this because IOException will also catch the file not found exception.
String value = "";
FileInputStream fis;
try {
fis = openFileInput(selectedFile);
byte[] input = new byte[fis.available()];
} catch (IOException e) {
e.printStackTrace();
}
Set the FileInputStream to a temporary value. null would be the best option, as in:
FileInputStream fis = null;
The reason for this is because if your try statement throws an error, then the fis will never me initialized. Then you'll have problems. If you don't exit the thing entirely, you should also add the statement after the try/catch blocks that tests if the value is null, just so that the program does not throw a null pointer exception.
So maybe something like:
if(fis == null) {
return; // Which will just end the method.
}
Also might want to put the try/catches together (you should still declare the other stuff outside of the try, at least anything you plan on using directly later on in the code) but it just might be more efficient coding wise), as in:
FileInputStream fis = null;
byte[] input = null;
try {
fis = openFileInput(selectedFile);
input = new byte[fis.available()];
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Now I am getting compile time error at line 30 and 38 that 'fin' might not have been initialized. but its perfectly to write it this way
import java.io.*;
class CopyFile {
public static void main(String args[]) throws IOException {
int i;
FileInputStream fin;//can't it be done like this?
FileOutputStream fout= new FileOutputStream(args[1]);
try{
//open input file
try{
fin = new FileInputStream(args[0]);
}
catch(FileNotFoundException e){
System.out.println("Input file Not Found");
return;
}
//open output file
try{
fout = new FileOutputStream(args[1]);
}
catch(FileNotFoundException e){
System.out.println("Error Opening File");
}
}
catch(ArrayIndexOutOfBoundsException e){
System.out.println("usage: Copyfile From to");
}
try{
do{
i = fin.read();
if(i!= -1)
fout.write(i);
}while(i != -1);
}
catch(IOException e){
System.out.println("file error");
}
fin.close();
fout.close();
}
}
I have seen it many time initialized like this. I think its due to the try blocks.
it might miss the initialization due to being in the try block and hence the error?
The problem is that you're not initializing the FileInputStream fin at all. Your code will look like this to the compiler:
FileInputStream fin;
try {
fin = ...
//more code goes here...
} catch (...) {
//exception handling...
} finally {
fin.close(); //fin is not even null for the compiler
}
In order to make the code work, initialize it at least with a null value and check if fin != null before using the close method.
FileInputStream fin = null;
try {
fin = ...
//more code goes here...
} catch (...) {
//exception handling...
} finally {
if (fin != null) {
fin.close(); //fin is not null, at least the JVM could close it
}
}
More info:
Java: Declaring Variables
Uninitialized variables and members in Java
FileInputStream fin=null;
Assign it null or FileInputStream object.
Local variable need to be assigned to some value before being used.
Though in the first try block, you are initializing fin as fin = new FileInputStream(args[0]);, your nested statements confuse the compiler. Just update your declaration as below:
FileInputStream fin = null;
Dont use try catch for an if and vice versa.
Try/catch is for when things go wrong behind your control and that is no part of normal program flow for example writing to a hard disk that is full....
Use if for normal error checking
In your example check your args array with an if block and then initialize your fin.