I'm writing an app that connect to a website and read one line from it. I do it like this:
try{
URLConnection connection = new URL("www.example.com").openConnection();
BufferedReader rd = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String response = rd.readLine();
rd.close();
}catch (Exception e) {
//exception handling
}
Is it good? I mean, I close the BufferedReader in the last line, but I do not close the InputStreamReader. Should I create a standalone InputStreamReader from the connection.getInputStream, and a BufferedReader from the standalone InputStreamReader, than close all the two readers?
I think it will be better to place the closing methods in the finally block like this:
InputStreamReader isr = null;
BufferedReader br = null;
try{
URLConnection connection = new URL("www.example.com").openConnection();
isr = new InputStreamReader(connection.getInputStream());
br = new BufferedReader(isr);
String response = br.readLine();
}catch (Exception e) {
//exception handling
}finally{
br.close();
isr.close();
}
But it is ugly, because the closing methods can throw exception, so I have to handle or throw it.
Which solution is better? Or what would be the best solution?
The general idiom for resource acquisition and release in Java is:
final Resource resource = acquire();
try {
use(resource);
} finally {
resource.release();
}
Note:
try should immediately follow the acquire. This means you can't wrap it in the decorator and maintain safety (and removing spaces or putting things on one line doesn't help:).
One release per finally, otherwise it wont be exception safe.
Avoid null, use final. Otherwise you'll have messy code and potential for NPEs.
Generally there is no need to close the decorator unless it has a further resource associated with it. However, you will generally need to flush outputs, but avoid that in the exception case.
The exception should either be passed through to the caller, or caught from a surrounding try block (Java leads you astray here).
ou can abstract this nonsense with the Execute Around idiom, so you don't have to repeat yourself (just write a lot of boilerplate).
Closing the BufferedReader is enough - this closes the underlying reader too.
Yishai posted a nice pattern for closing the streams (closing might throw another exception).
Is it good? I mean, I close the BufferedReader in the last line, but I do not close the InputStreamReader.
Apart from the fact that it should be done in the finally (so that the close is ensured, even in case of an exception), it's fine. The Java IO classes uses the decorator pattern. The close will be delegated to the underlying streams.
But it is ugly, because the closing methods can throw exception, so I have to handle or throw it.
When the close throws an exception, it often just means that the other side has been closed or deleted, which is completely out of your control. You can at highest log or ignore it. In a simple application I would just ignore it. In a mission critical application I would log it, just to be sure.
In a nut, your code can be rewritten as:
BufferedReader br = null;
try {
URLConnection connection = new URL("www.example.com").openConnection();
br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String response = br.readLine();
}catch (Exception e) {
//exception handling
}finally{
if (br != null) try { br.close(); } catch (IOException ignore) {}
}
In Java 7 there will be automatic resource handling which would made your code as concise as:
try (BufferedReader br = new InputStreamReader(new URL("www.example.com").openStream())) {
String response = br.readLine();
} catch (Exception e) {
//exception handling
}
See also:
Java IO tutorial
C# "using" keyword in Java
How to use URLConnection
BufferedReader br = null;
You are declaring a variable without assigning it (null doesn't count - it is a useless assignment in this case). This is a code "smell" in Java (ref Effective Java; Code Complete for more on variable declaration).
}finally{
br.close();
isr.close();
}
First, you only need to close the top-most stream decorator (br will close isr). Secondly, if br.close() threw an exception, isr.close() would not be called, so this is not sound code. Under certain exception conditions, your code will hide the originating exception with a NullPointerException.
isr = new InputStreamReader(connection.getInputStream());
If the (admittedly unlikely) event that the InputStreamReader constructor threw any kind of runtime exception, the stream from the connection would not be closed.
Make use of the Closeable interface to reduce redundancy.
Here is how I would write your code:
URLConnection connection = new URL("www.example.com").openConnection();
InputStream in = connection.getInputStream();
Closeable resource = in;
try {
InputStreamReader isr = new InputStreamReader(in);
resource = isr;
BufferedReader br = new BufferedReader(isr);
resource = br;
String response = br.readLine();
} finally {
resource.close();
}
Note that:
no matter what kind of exception is thrown (runtime or checked) or where, the code does not leak stream resources
there is no catch block; exceptions should be passed up to where the code can make a sensible decision about error handling; if this method was the right place, you'd surround all of the above with try/catch
A while back, I spent some time thinking about how to avoid leaking resources/data when things go wrong.
I think it will be better to place the
closing methods in the finally block
Yes, always. Because an exception might occur and resources aren't released/closed properly.
You only need to close the most outer reader because it will be responsible for closing any enclosing readers.
Yes, it's ugly... for now. I think there are plans for an automatic resource management in Java.
I'd use apache commons IO for this, as others have suggested, mainly IOUtils.toString(InputStream) and IOUtils.closeQuietly(InputStream):
public String readFromUrl(final String url) {
InputStream stream = null; // keep this for finally block
try {
stream = new URL(url).openConnection().getInputStream(); // don't keep unused locals
return IOUtils.toString(stream);
} catch (final IOException e) {
// handle IO errors here (probably not like this)
throw new IllegalStateException("Can't read URL " + url, e);
} finally {
// close the stream here, if it's null, it will be ignored
IOUtils.closeQuietly(stream);
}
}
You don't need multiple close statements for any of the nested streams and readers in java.io. It's very rare to need to close more than one thing in a single finally - most of the constructors can throw an exception, so you would be trying to close things you haven't created yet.
If you want to close the stream whether or not the read succeeds, then you need to put in into a finally.
Don't assign null to variables and then compare them to see whether something happened earlier; instead structure your program so the path where you close the stream can only be reached if the exception is not thrown. Apart from the variables used to iterate in for loops, variables should not need to change value - I tend to mark everything final unless there is a requirement to do otherwise. Having flags around your program to tell you how you got to the code currently being executed, and then changing behaviour based on those flags, is very much a procedural (not even structured) style of programming.
How you nest the try/catch/finally blocks depends on whether you want to handle the exceptions thrown by the different stages differently.
private static final String questionUrl = "http://stackoverflow.com/questions/3044510/";
public static void main ( String...args )
{
try {
final URLConnection connection = new URL ( args.length > 0 ? args[0] : questionUrl ).openConnection();
final BufferedReader br = new BufferedReader ( new InputStreamReader (
connection.getInputStream(), getEncoding ( connection ) ) );
try {
final String response = br.readLine();
System.out.println ( response );
} catch ( IOException e ) {
// exception handling for reading from reader
} finally {
// br is final and cannot be null. no need to check
br.close();
}
} catch ( UnsupportedEncodingException uee ) {
// exception handling for unsupported character encoding
} catch ( IOException e ) {
// exception handling for connecting and opening reader
// or for closing reader
}
}
getEncoding needs to inspect the results of the connection's getContentEncoding() and getContentType() to determine the encoding of the web page; your code just uses the platform's default encoding, which may well be wrong.
Your example though is unusual in structured terms, since it is very procedural; normally you would separate the printing and the retrieving in a larger system, and allow the client code to handle any exception (or sometimes catch and create a custom exception):
public static void main ( String...args )
{
final GetOneLine getOneLine = new GetOneLine();
try {
final String value = getOneLine.retrieve ( new URL ( args.length > 0 ? args[0] : questionUrl ) );
System.out.println ( value );
} catch ( IOException e ) {
// exception handling for retrieving one line of text
}
}
public String retrieve ( URL url ) throws IOException
{
final URLConnection connection = url.openConnection();
final InputStream in = connection.getInputStream();
try {
final BufferedReader br = new BufferedReader ( new InputStreamReader (
in, getEncoding ( connection ) ) );
try {
return br.readLine();
} finally {
br.close();
}
} finally {
in.close();
}
}
As McDowell pointed out, you may need to close the input stream if new InputStreamReader throws.
In scope of Java 8 I would use alike:
try(Resource resource = acquire()) {
use(resource);
reuse(resource);
}
Related
As per as my knowledge we use try catch as follows:
try {
//Some code that may generate exception
}
catch(Exception ex) {
}
//handle exception
finally {
//close any open resources etc.
}
But in a code I found following
try(
ByteArrayOutputStream byteArrayStreamResponse = new ByteArrayOutputStream();
HSLFSlideShow pptSlideShow = new HSLFSlideShow(
new HSLFSlideShowImpl(
Thread.currentThread().getContextClassLoader()
.getResourceAsStream(Constants.PPT_TEMPLATE_FILE_NAME)
));
){
}
catch (Exception ex) {
//handel exception
}
finally {
//close any open resource
}
I am not able to understand why this parentheses () just after try.
What is the usage of it? Is it new in Java 1.7? What kind of syntax I can write there?
Please also refer me some API documents.
It is try with Resources syntax which is new in java 1.7. It is used to declare all resources which can be closed. Here is the link to official documentation.
https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
static String readFirstLineFromFile(String path) throws IOException {
try (BufferedReader br =
new BufferedReader(new FileReader(path))) {
return br.readLine();
}
}
In this example, the resource declared in the try-with-resources statement is a BufferedReader. The declaration statement appears within parentheses immediately after the try keyword. The class BufferedReader, in Java SE 7 and later, implements the interface java.lang.AutoCloseable. Because the BufferedReader instance is declared in a try-with-resource statement, it will be closed regardless of whether the try statement completes normally or abruptly (as a result of the method BufferedReader.readLine throwing an IOException).
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.
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 have a Java program that reads data from a TCP source all works fine, except when my program (which acts as a client to the data source) is faster then then the source can respond BufferedReader.ready() throws an exception that closes my TCP connection, as it should. Is there any preferred way/method that I can keep the BufferedReader waiting for new input since my source can sometimes have a slight delay.
Here is the part that i am talking about:
public aDataServer(String host, int port, StreamConnection aConnection) throws UnknownHostException, IOException {
this.aConnection = aConnection;
ndataServerSocket = new Socket(Inet4Address.getByName(host),port);
ndataServerReader = new BufferedReader(new InputStreamReader(ndataServerSocket.getInputStream()));
}
public void run() {
try {
RemoteDevice dev = RemoteDevice.getRemoteDevice(aConnection);
OutputStream outputStream = aConnection.openOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(outputStream);
do {
try {
String ndata = ndataServerReader.readLine();
osw.write(ndata+"\n");
osw.flush();
LOG.log(Level.INFO,"Sent");
} catch(IOException io) {
LOG.log(Level.SEVERE, "Client device({0}) disconnected: \n{1}", new Object[]{dev.getFriendlyName(true), io.getMessage()});
break;
}
}while(ndataServerReader.ready());
} catch (IOException ioe) {
LOG.severe(ioe.getMessage());
} finally {
try {
if (ndataServerSocket != null) {
ndataServerSocket.close();
}
if (ndataServerReader
!= null) {
ndataServerReader.close();
}
} catch (IOException ex) {
LOG.log(Level.SEVERE, ex.getMessage());
}
}
You shouldn't be using ndataServerReader.ready(). Your do/while loop (which should almost certainly just be a while loop) appears to assume that ndataServerReader.ready() indicates there's more data to be read, which is not what it's for.
The Javadoc for Reader describes the ready() method as:
Tells whether this stream is ready to be read.
Returns: True if the next read() is guaranteed not to block for input, false
otherwise. Note that returning false does not guarantee that the next
read will block.
In other worse, Reader.ready() will return false if the reader will wait for more data before returning if you attempt to read from it. This does not mean the Reader is done, and in fact you should expect this method to return false often when working with a network stream, as it could easily have delays.
Your code currently is likely reading one line (in the do block) then checking if the reader is ready (in the while), which it probably isn't, and then exiting successfully. No exceptions are being thrown - you'd see a SEVERE level logging message if they were.
Instead of using ready(), take advantage of the documented behavior of readLine() that says it returns:
A String containing the contents of the line, not including any
line-termination characters, or null if the end of the stream has been
reached
In other words, simply doing:
String ndata = reader.readLine();
while (ndata != null) {
osw.write(ndata+"\n");
osw.flush();
LOG.log(Level.INFO,"Sent");
ndata reader.readLine();
}
Is sufficient to read the whole input stream.
Reference reading: What's the difference between (reader.ready()) and using a for loop to read through a file?
Wrote up a basic file handler for a Java Homework assignment, and when I got the assignment back I had some notes about failing to catch a few instances:
Buffer from file could have been null.
File was not found
File stream wasn't closed
Here is the block of code that is used for opening a file:
/**
* Create a Filestream, Buffer, and a String to store the Buffer.
*/
FileInputStream fin = null;
BufferedReader buffRead = null;
String loadedString = null;
/** Try to open the file from user input */
try
{
fin = new FileInputStream(programPath + fileToParse);
buffRead = new BufferedReader(new InputStreamReader(fin));
loadedString = buffRead.readLine();
fin.close();
}
/** Catch the error if we can't open the file */
catch(IOException e)
{
System.err.println("CRITICAL: Unable to open text file!");
System.err.println("Exiting!");
System.exit(-1);
}
The one comment I had from him was that fin.close(); needed to be in a finally block, which I did not have at all. But I thought that the way I have created the try/catch it would have prevented an issue with the file not opening.
Let me be clear on a few things: This is not for a current assignment (not trying to get someone to do my own work), I have already created my project and have been graded on it. I did not fully understand my Professor's reasoning myself. Finally, I do not have a lot of Java experience, so I was a little confused why my catch wasn't good enough.
Buffer from file could have been null.
The file may be empty. That is, end-of-file is reach upon opening the file. loadedString = buffRead.readLine() would then have returned null.
Perhaps you should have fixed this by adding something like if (loadedString == null) loadedString = "";
File was not found
As explained in the documentation of the constructor of FileInputStream(String) it may throw a FileNotFoundException. You do catch this in your IOException clause (since FileNotFoundException is an IOException), so it's fine, but you could perhaps have done:
} catch (FileNotFoundException fnfe) {
System.err.println("File not fonud!");
} catch (IOException ioex {
System.err.println("Some other error");
}
File stream wasn't closed
You do call fin.close() which in normal circumstances closes the file stream. Perhaps he means that it's not always closed. The readLine could potentially throw an IOException in which case the close() is skipped. That's the reason for having it in a finally clause (which makes sure it gets called no matter what happens in the try-block. (*)
(*) As #mmyers correctly points out, putting the close() in a finally block will actually not be sufficient since you call System.exit(-1) in the catch-block. If that really is the desired behavior, you could set an error flag in the catch-clause, and exit after the finally-clause if this flag is set.
But what if your program threw an exception on the second or third line of your try block?
buffRead = new BufferedReader(new InputStreamReader(fin));
loadedString = buffRead.readLine();
By this point, a filehandle has been opened and assigned to fin. You could trap the exception but the filehandle would remain open.
You'll want to move the fin.close() statement to a finally block:
} finally {
try {
if (fin != null) {
fin.close();
}
} catch (IOException e2) {
}
}
Say buffRead.readLine() throws an exception, will your FileInputStream ever be closed, or will that line be skipped? The purpose of a finally block is that even in exceptional circumastances, the code in the finally block will execute.
There are a lot of other errors which may happen other than opening the file.
In the end you may end up with a fin which is defined or not which you have to protect against null pointer errors, and do not forget that closing the file can throw a new exception.
My advice is to capture this in a separate routine and let the IOExceptions fly out of it :
something like
private String readFile() throws IOException {
String s;
try {
fin = new FileInputStream(programPath + fileToParse);
buffRead = new BufferedReader(new InputStreamReader(fin));
s = buffRead.readLine();
fin.close();
} finally {
if (fin != null {
fin.close()
}
}
return s
}
and then where you need it :
try {
loadedString = readFile();
} catch (IOException e) {
// handle issue gracefully
}