Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 5 years ago.
Improve this question
I have the following code which yields me a "Syntax error, insert "Finally" to complete TryStatement".
private synchronized void writeDurationToFile(String sFileName, Date dtStartTime, long lDuration, String sStatus) {
if(!sRHTimeStamp.isEmpty()) {
String sFullPath = sFileName + "_" + sRHTimeStamp + ".csv";
try {
if(!Paths.get(sFullPath).toFile().exists()) {
try( FileWriter fw = new FileWriter(sFullPath);
PrintWriter pw = new PrintWriter(fw);) {
pw.println("Start\tEnd\tDuration");
pw.println(TimeUtils.getTimeStamp(true, dtStartTime) + "," + lDuration + "," + sStatus);
}
}else{
try(FileWriter fw = new FileWriter(sFullPath, true); PrintWriter pw = new PrintWriter(fw);) {
pw.println(TimeUtils.getTimeStamp(true, dtStartTime) + "," + lDuration + "," + sStatus);
}
}
} //Here I get the error notification
}
}
Why do I get this error, and how can I write it better to eliminate the duplication of
pw.println(TimeUtils.getTimeStamp(true, dtStartTime) + "," + lDuration
+ "," + sStatus);
but still use the "try-with-resource" implementation.
I based my code on http://tutorials.jenkov.com/java-exception-handling/try-with-resources.html
Your larger try block is not a try-with-resources, but rather a standard try. It therefore needs to have either a catch or finally block added to it.
try {..} is not a try-with-resource statement.
Your try{...} may make sense as try-with-resource will close resources for you but not handle exceptions thrown during statements execution of the try block.
But note that a classic try has to be declared with a finally or a catch statement or both.
Your method writeDurationToFile() doesn't throw IOException while you code may throw it.
So you should either add it in the method declaration :
private synchronized void writeDurationToFile(String sFileName, Date dtStartTime, long lDuration, String sStatus) throws IOException
and remove the try{...} to allow the client code to handle the IOException.
Or another way would be catching the exception in the method by completing the try statement with a catch.
In this way, the client code doesn't need to handle the IOException :
try { //classic try
// try-with-resource
try(FileWriter fw = new FileWriter(sFullPath);
PrintWriter pw = new PrintWriter(fw)) {
...
}
...
// other try-with-resource
try(FileWriter fw = new FileWriter(sFullPath, true);
PrintWriter pw = new PrintWriter(fw)) {
...
}
}
// catch exceptions thrown in the block/body of the `try-with-resource` statements
catch (IOException e){
// exception handling
}
Related
This question already has an answer here:
Sonar: How to use try-with-resources to close FileOutputStream
(1 answer)
Closed 5 years ago.
I am having the trouble of close the "FileOutputStream" from sonar . Eventhough I closed the file. From the document of Sonar I donĀ“t understand the error.
I looked at the post
SONAR issue - Close this FileInputStream.
This also not solving my problem.
public void trainL2lSupport(String training_path, String model_path) throws Exception {
BasicConfigurator.configure();
String[] options = { "-s 1" };
FileOutputStream ms = new FileOutputStream(model_path); // This one is producing the error.
classifier.setOptions(options);
logger.info(msg + classifier.globalInfo());
loader.setFile(new File(training_path));
Instances data_set = loader.getDataSet();
data_set.setClassIndex(data_set.numAttributes() - 1);
classifier.buildClassifier(data_set);
Evaluation evaluation = new Evaluation(data_set);
evaluation.crossValidateModel(classifier, data_set, 40, new Random(1));
logger.info(evaluation.toSummaryString());
logger.info(msg1 + timer.stop());
// oos = new ObjectOutputStream(ms);
try {
ObjectOutputStream oos = new ObjectOutputStream(ms);
oos.writeObject(classifier);
oos.flush();
oos.close();
logger.info(msg3+ evaluation.toSummaryString());
logger.info(msg1 + timer.stop());
logger.info("File closed safetly");
} catch(Exception e) {
}
finally {
ms.close();
}
}
How to solve it ?
Use the try-with-resources statement.
If an exception is thrown from any of the lines of code before the try block, the FileOutputStream is never closed. Hence the Sonar warning.
Also, indent your code, don't catch Exception (you should have another warning for that), and don't ignore exceptions like you're doing.
I know that the resource you pass with a try, will be closed automatically if the resource has AutoCloseable implemented. So far so good. But what do I do when i have several resources that I want automatically closed. Example with sockets;
try (Socket socket = new Socket()) {
input = new DataInputStream(socket.getInputStream());
output = new DataOutputStream(socket.getOutputStream());
} catch (IOException e) {
}
So I know the socket will be closed properly, because it's passed as a parameter in the try, but how should the input and output be closed properly?
Try with resources can be used with multiple resources by declaring them all in the parenthesis. See the documentation
Relevant code excerpt from the linked documentation:
public static void writeToFileZipFileContents(String zipFileName,
String outputFileName)
throws java.io.IOException {
java.nio.charset.Charset charset =
java.nio.charset.StandardCharsets.US_ASCII;
java.nio.file.Path outputFilePath =
java.nio.file.Paths.get(outputFileName);
// Open zip file and create output file with
// try-with-resources statement
try (
java.util.zip.ZipFile zf =
new java.util.zip.ZipFile(zipFileName);
java.io.BufferedWriter writer =
java.nio.file.Files.newBufferedWriter(outputFilePath, charset)
) {
// Enumerate each entry
for (java.util.Enumeration entries =
zf.entries(); entries.hasMoreElements();) {
// Get the entry name and write it to the output file
String newLine = System.getProperty("line.separator");
String zipEntryName =
((java.util.zip.ZipEntry)entries.nextElement()).getName()
newLine;
writer.write(zipEntryName, 0, zipEntryName.length());
}
}
}
If your objects don't implement AutoClosable (DataInputStream does), or must be declared before the try-with-resources, then the appropriate place to close them is in a finally block, also mentioned in the linked documentation.
Don't worry, things will "just work". From Socket's documentation:
Closing this socket will also close the socket's InputStream and OutputStream.
I understand your concern about not explicitly calling close() on the input and output objects and in fact it's generally better to ensure all resources are automatically managed by the try-with-resources block, like this:
try (Socket socket = new Socket();
InputStream input = new DataInputStream(socket.getInputStream());
OutputStream output = new DataOutputStream(socket.getOutputStream());) {
} catch (IOException e) {
}
This would have the effect that the socket object would be "closed multiple times", but that should not do any harm (this is one of the reasons why it's generally advised that all implementations of close() be made idempotent).
In addition to the above answers, This is the improvement added in Java 9.
Java 9 try-with-resources makes an improved way of writing code. Now you can declare the variable outside the try block and use them inside try block directly.because of this you will get following benefits.
The Resources which it declared outside try( which is effectively final or final) can be automatically close by automatic resource management by just adding them in the try block.
You no need to re-refer objects declared outside try block nor need to close them manually as we need to do in Java 7.
It also helps to write clean code.
try-with-resource can we write like this in Java 9.
public void loadDataFromDB() throws SQLException {
Connection dbCon = DriverManager.getConnection("url", "user", "password");
try (dbCon; ResultSet rs = dbCon.createStatement().executeQuery("select * from emp")) {
while (rs.next()) {
System.out.println("In loadDataFromDB() =====>>>>>>>>>>>> " + rs.getString(1));
}
} catch (SQLException e) {
System.out.println("Exception occurs while reading the data from DB ->" + e.getMessage());
}
}
Here automatic resource management will automatically close both the objects dbCon & rs.
For the better understanding of the list of above define use cases please find some Java 7 code.
Example 1:
public void loadDataFromDB() throws SQLException {
Connection dbCon = DriverManager.getConnection("url", "user", "password");
try (ResultSet rs = dbCon.createStatement().executeQuery("select * from emp")) {
while (rs.next()) {
System.out.println("In loadDataFromDB() =====>>>>>>>>>>>> " + rs.getString(1));
}
} catch (SQLException e) {
System.out.println("Exception occurs while reading the data from DB ->" + e.getMessage());
} finally {
if (null != dbCon)
dbCon.close();
}
}
Example 2:
// BufferedReader is declared outside try() block
BufferedReader br = new BufferedReader(new FileReader("C://readfile/input.txt"));
try (BufferedReader inBr = br) {
// ...
}
} catch (IOException e) {
// ...
}
In the above samples you can see if the object is ouside try then either we need to close manually or re-refer it. Also in the case of multiple objects in the try block, it looks messy and even if you declared inside try then you can't use outside try block.
Answers above are great but there are some cases when try-with-resources doesn't help.
Take a look at this code example:
private static byte[] getFileBytes(Collection<String> fileContent) throws CustomServiceException {
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(baos))) {
for (String fileLine : fileContent) {
writer.append(fileLine);
writer.newLine();
}
}
return baos.toByteArray();
} catch (IOException e) {
throw new CustomServiceException(SC_INTERNAL_SERVER_ERROR, "Unable to serialize file data.");
}
}
In this example u can't just use try-with-resources block cause writer has to flush the output buffer to the underlying character stream so placing writer into try-with-resources block won't do the trick and method will return empty array.
This question already has answers here:
Why is declaration required in Java's try-with-resource
(3 answers)
Closed 9 years ago.
try(PrintWriter f = new PrintWriter(new BufferedWriter(new FileWriter("abc.txt")));)
{}
catch(IOException ex)
{
ex.printStackTrace();
}
Above works fine. But when I do
PrintWriter f;
try(f = new PrintWriter(new BufferedWriter(new FileWriter("abc.txt")));)
{}
catch(IOException ex)
{
ex.printStackTrace();
}
It throws errors. Why is it so? I was testing this new feature and I was of the opinion I would take the 2nd method and after the try-catch statement would print the resource PrintWriter f - which should be null if try-with-resource statement works as expected. Why is the 2nd way not allowed?
Also how could I test it by method 1?
Because try-with-resources actually adds the finally block for you in order to close the resources after usage, so they should not be usable anyway (after you leave your try block).
So this code
try(PrintWriter f = new PrintWriter(new BufferedWriter(new FileWriter("abc.txt")));) {
} catch(IOException ex) {
ex.printStackTrace();
}
actually translates into
PrintWriter f = null;
try {
f = new PrintWriter(new BufferedWriter(new FileWriter("abc.txt")));)
// now do something
} catch(IOException ex) {
ex.printStackTrace();
}
finally {
try {
f.close();
catch(IOException ex) {}
}
}
So this was the original purpose, save you from the bloated code and allow you to take care just about try block and leave the rest on JVM. Also see what Oracle docs has to say about this.
The code below, I believe, answers your question, with an unexpected result.
PrintWriter t = null;
try( PrintWriter f = new PrintWriter( new BufferedWriter(
new FileWriter( "abc.txt" ) ) ) ) {
f.println( "bar" );
t = f;
} catch( IOException ex ) {
ex.printStackTrace();
}
System.out.println( t );
t.println( "foo" );
t.close();
Output:
java.io.PrintWriter#1fc4bec
But, nothing is added to the file, as the writer was closed by the try.
Edit: If you want to play with TWR, write a class that implements AutoClosable, for example:
public class Door implements AutoCloseable {
public Door() {
System.out.println( "I'm opening" );
}
public void close() {
System.out.println( "I'm closing" );
}
public static void main( String[] args ) {
try( Door door = new Door() ) { }
}
}
Output:
I'm opening
I'm closing
Not perfectly sure, but doing some sophisticated guesses:
The value of f after the catch block is potentially undefined. Therefore you would have to add all kinds of checks to verify whether the Object has been created, used, and/or is closed. But if you need all those checks, it would be simpler to not use that idiom in the first place.
The JIT can happily optimize code with a block-local variable.
The AutoClosure variable must not be set to a different variable during the try block, but can be afterwards. Maybe that's just too complicated for the JIT to check.
I have discovered possibility of having code "after return" using finally, here is some example:
int foo() {
BufferedReader br = ...;
try {
// cca 20 lines with 4 returns in different if-else clauses etc
//example:
if(something) {
return 0;
} else {
return 1;
}
} finally {
br.close();
}
}
As (in my opinion much more lazy) alternativity to:
int foo() {
BufferedReader br = ...;
int toReturn;
// cca 20 lines with 4 ASSIGMENTS in different if-else clauses etc
//example:
if(something) {
toReturn = 0;
} else {
toReturn = 1;
}
br.close();
return toReturn;
}
So, the question is, which is faster, more readable, and yes, in this case, i am really closing a BufferedReader, so is try-finnaly for this or am i using it wrong way?
Without using the try/catch/finally, if an exception is thrown, your BufferedReader won't be closed properly, causing a memory leak, potential unwanted file locking...
Using finally, your BufferedReader will be closed, even if an exception is thrown while processing the try block.
But as your BufferedReader instantiation can also throw an exception, you should include it in your try block:
BufferedReader br = null;
try {
br = ...;
// do your stuff
}
catch (Exception e) {
// handle exception
}
finally {
if(br != null)
br.close();
}
If you're using Java 7 or newer, go with the elegant Try-with-resources, as stated by Arnaud.
If there is an exception throws, both your code fail since first case you are not catching exception and second case there are no evidence of handling exception.
finally will execute any way here.
If your BufferedReader get input by file read, in a case which file not found both ways are not useful.
The second one is actually unacceptable. You will not close the buffer in case of exception.
I advise you to use the try-with-resources statement (intended for that purpose):
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
//do what you want with the buffer. It will automatically be closed.
return;
}
See The try-with-resources Statement
am i using it wrong way?
yes you are. What if say something is a method call and it throws exception, then your br is never closed. While finally makes sure that in any case it will get execute*
`* - there are some conditions where you can avoid finally clause execution
I am trying to return a String from the following method.
public String openCon() {
try {
Scanner scan = new Scanner(System.in);
URL sitex = new URL("http://" + scan.nextLine());
URLConnection connection = sitex.openConnection();
Object content = sitex.getContent();
BufferedReader in = new BufferedReader(new InputStreamReader(sitex.openStream()));
String str;
String x = "1";
while ((str = in.readLine()) != null) {
x += str;
}
in.close();
return x;
}
catch(Exception e) {
System.out.println(e);
}
}
The problem isn't returning from the try block - the problem is that you aren't returning anything if an exception is thrown. You're catching the exception... but then reaching the end of the method without returning anything. (To put it in more technical terminology: the end of a non-void method should not be reachable.)
Personally, I would just remove the catch block entirely, and add throws declarations for any exceptions which are thrown within the body. You're not really handling the exceptions - you're just printing them out and ignoring them, which is very rarely a good idea. Catching Exception is usually a pretty bad idea to start with.
As an aside, you should also close your BufferedReader and URLConnection values in a finally block so they're closed even in the case of an exception. I'd also suggest either passing a fixed encoding name to InputStreamReader, or using a higher-level HTTP client API which will use the content-type header from the response. Oh, and use StringBuilder instead of string concatenation in a loop.
Why not initialise the variable before the try statement, and place the return statement after it?
If there's an exception before the return statement, the method won't return anything. Since you're not really handling the exception, I recommend you just let it bubble up and handle it at a higher level. This may be the main method if there's no better place. You will need to declare the method as throws IOException and possibly add other exception classes.
Also, use try-with-resources to ensure your instances (BufferedReader and InputStreamReader) are closed properly.
You should return something in the catch block, for example:
catch(Exception e) {
System.out.println(e);
return "";
}
Use:
String result = ""
try{
result = "OK";
}catch (Exception e){
result = e.toString();
}finally{
return result;
}