My doubt mainly arises while reading sockets, within the following code:
String hostName = args[0];
int portNumber = Integer.parseInt(args[1]);
try (
Socket echoSocket = new Socket(hostName, portNumber);
PrintWriter out =
new PrintWriter(echoSocket.getOutputStream(), true);
BufferedReader in =
new BufferedReader(
new InputStreamReader(echoSocket.getInputStream()));
BufferedReader stdIn =
new BufferedReader(
new InputStreamReader(System.in))
) {
String userInput;
while ((userInput = stdIn.readLine()) != null) {
out.println(userInput);
System.out.println("echo: " + in.readLine());
}
Link:http://docs.oracle.com/javase/tutorial/networking/sockets/examples/EchoClient.java
In the above code, as I understand, PrintWriter and BufferedReader are the resources, however I also read in the trywithreasources block, as soon as it ends, all resources within it are closed. But if closing of the resource implies destruction of the object, that would mean stdIn and in are destroyed and it is a separate instance outside the block. Is it so?
The try-with-resource statement will only close resources declared in the parentheses between the inside the try.
try ( /*anything declared here will be closed*/) {
}
The when the try ends, the try with resource will call close() on any resource declared. This doesn't necessarily "destroy" an object like a destructor in C, but it is often used that way. The variable will also fall out of scope outside the try so it can be garbage collected.
IN your example stdIn wraps System.in so System.in WILL BE CLOSED. However since it is still in scope after the try, it will not be garbage collected. (but you can't write to it anymore)
Try-with-resource is just "syntatic sugar" and will be compiled into something like this:
Socket echoSocket =null
PrintWriter out =null
BufferedReader in =null
BufferedReader stdIn =null
try{
echoSocket = new Socket(hostName, portNumber);
out =
new PrintWriter(echoSocket.getOutputStream(), true);
in =
new BufferedReader(
new InputStreamReader(echoSocket.getInputStream()));
stdIn =
new BufferedReader(
new InputStreamReader(System.in));
String userInput;
while ((userInput = stdIn.readLine()) != null) {
out.println(userInput);
System.out.println("echo: " + in.readLine());
}
}finally{
if(stdIn !=null){
try{
stdIn.close()
}catch(Exception e){
//surpress exception if needed
}
}
if(in !=null){
try{
in.close()
}catch(Exception e){
//surpress exception
}
}
if(out !=null){
try{
out.close()
}catch(Exception e){
//surpress exception
}
}
if(echoSocket !=null){
try{
echoSocket.close()
}catch(Exception e){
//surpress exception
}
}
}
Notice that the resources are closed in reverse order to solve the nesting issue. If something threw an exception in the try block AND something else threw an exception in the finally block, then the "surpress exception" gets added to the original Exception object which can be retrieve via the new Throwable.getSuppressed() method. This is so the stacktrace correctly shows the original exception that was thrown inside the try.
for more information about try-with-resource see Oracle's tutorial: http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
Looking at your try-with-resources, let's take only the part wrapping System.in.
try (
...
BufferedReader stdIn =
new BufferedReader(
new InputStreamReader(System.in))
)
stdIn is an object that wraps an InputStreamReader object that wraps an InputStream object. That InputStream object is (unless you've changed it) the Java process' standard input.
When you exit the try block, it will call stdIn.close(), which will cascade and call close() on the InputStreamReader which will cascade and call close() on the object referenced by System.in.
There is no destruction in Java. If the objects referenced by the variables above become unreachable from within your program, they will be garbage collected.
if closing of the resource implies destruction of the object
It doesn't. There is no such thing as 'destruction' in Java.
that would mean stdIn and in are destroyed
No it doesn't.
and it is a separate instance outside the block. Is it so?
No.
Related
I am writing a method but see this error: may fail to close stream.
According to some solutions on different posts, I have added try and catch within the finally block. I also added IOUtils.closeQuietly(fullObject, (Log) LOGGER). But it still doesn't work. Anyone can help take a look? Thanks!
S3Object fullObject = null;
StringBuffer buffer = new StringBuffer();
try {
S3Object s3Response = s3Client.getObject(s3BucketName, s3Key);
BufferedReader reader = new BufferedReader(new InputStreamReader(s3Response.getObjectContent()));
String line;
while ((line = reader.readLine()) != null) {
buffer.append(line);
}
} finally {
if (fullObject != null) {
try {
fullObject.close();
} catch (IOException ex) {
throw new RuntimeException(ex);
}
IOUtils.closeQuietly(fullObject, (Log) LOGGER);
}
}
return buffer.toString();
}
You should be using Java 7+ try with resources. It will take care of closing the resources you declare in the list. Any exceptions that may be thrown in the process of closing will be dealt with appropriately. (They are either allowed to propagate, or they are "suppressed" if an exception was already propagating.)
Your code using try with resources would look like this. It is half the length of the original version AND it won't have any resource leaks. You "win" both ways.
try (S3Object s3Response = s3Client.getObject(s3BucketName, s3Key);
BufferedReader reader = new BufferedReader(
new InputStreamReader(s3Response.getObjectContent()));
)
{
StringBuffer buffer = new StringBuffer();
String line;
while ((line = reader.readLine()) != null) {
buffer.append(line);
}
return buffer.toString();
}
Notice that I have gotten rid of fullObject which your code wasn't using.
There are actually two managed resources in the above: the s3Response and the reader. It might not be strictly necessary to close both, but (IMO) closing them anyway is the correct thing to do ... from the perspective of readability, if nothing else.
(It may also be possible to do the "read content as a string" more simply and/or more efficiently, but that is outside of the scope of this question.)
InputStreamReader implements AutoCloseable. This means that the intended use is try-with-resources:
try (InputStreamReader reader = new InputStreamReader(s3Response.getObjectContent()) {
...
}
This should always close the stream irrespective of how the block exits (i.e. through normal completion, catch or finally clauses).
The same is true for S3Object and BufferedReader. They can all be declared as resources within the same try block.
See https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html for more details.
I have used Buffered writer a few times but there is a line of code I am not sure of its purpose. The code is below
BufferedWriter writefile = null;
I wonder if anyone could tell me what this line of code does and if it is needed.
Initialization of BufferedReader can involve calling constructors which can throw exceptions like new BufferedReader(new FileReader(fileLocation)) because calling FileReader constructor may throw FileNotFoundException if location in fileLocation doesn't point to existing and accessible file.
To handle this exception we move initialization in try section. Theoretically we could write
try{
BufferedReader br = new BufferedReader(new FileReader(fileLocation));
//...
}catch(FileNotFoundException e){
//handle exception
}
but then in finally section we want to handle closing that reader and prevent resource leaking. So we need to add
finally{
br.close();
}
Problem 1 - scope
We can't access br from finally section because it was declared in try section so its scope is limited to it.
Solution would be declaring it outside of try but initializing in try. So lets do
BufferedReader br;
try{
br = new BufferedReader(new FileReader(fileLocation));
//...
}catch(FileNotFoundException e){
//handle exception
}finally{
br.close();
}
Problem 2 - usage of possibly uninitialized variable
We can't call br.close() because if exception will be thrown br will not be initialized (not even with null), so compiler can't compile such code.
Solution is to explicitly assign null to br before try section. This will allow us to know in finally section if br was properly initialized and need to be closed or not (if it still holds null). So we used to write code like
BufferedReader br = null;
try{
br = new BufferedReader(new FileReader(fileLocation));
//...
}catch(FileNotFoundException e){
//handle exception
}finally{
if (br != null){
br.close();
}
}
Above was used pre Java 7, before try-with-resources was introduced. Now to have same functionality as above all we need is
try (BufferedReader br = new BufferedReader(new FileReader(fileLocation))) {
//...
}catch(FileNotFoundException e){
//handle exception
}
I am trying to invoke the following method inside a while loop. First time, it invokes fine but on 2nd loop execution, it throws an IOException
public String getInputString(String prompt){
System.out.print(prompt);
String inputLine = null;
try(BufferedReader br = new BufferedReader(new InputStreamReader(System.in))){
inputLine = br.readLine();
if(inputLine.length() == 0){
return null;
}
}
catch(IOException e){
e.printStackTrace();
}
return inputLine;
}
I am getting this IOException:
java.io.IOException: Stream closed
at java.io.BufferedInputStream.getBufIfOpen(BufferedInputStream.java:162)
at java.io.BufferedInputStream.read(BufferedInputStream.java:325)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:283)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:325)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:177)
at java.io.InputStreamReader.read(InputStreamReader.java:184)
at java.io.BufferedReader.fill(BufferedReader.java:154)
at java.io.BufferedReader.readLine(BufferedReader.java:317)
at java.io.BufferedReader.readLine(BufferedReader.java:382)
at ch5.GameHelper.getInputString(GameHelper.java:14)
at ch5.SimpleDotComTestDrive.main(SimpleDotComTestDrive.java:19)
On the other hand, it is working fine when i try to execute it as follows:
try{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
inputLine = br.readLine();
if(inputLine.length() == 0){
return null;
}
}
catch(IOException e){
e.printStackTrace();
}
What is the reason for such a behaviour?
I suspect you're calling getInputString more than once.
The first time, it should work fine - but then you're closing System.in (by closing the BufferedReader wrapping InputStreamReader wrapping System.in)... which means the next time you try to read from System.in, you won't be able to.
If you remove the try-with-resources statement, you could still have problems, because you'll be creating multiple readers around the same stream - if one of those reads more input than you actually use, it won't be available later on.
I suggest you create a BufferedReader wrapping an InputStreamReader wrapping System.in once, at the start of your program, and use that BufferedReader instance everywhere.
I have a method that receives a string with a filepath, and i have created all the code for reading the file, with the try a catch blocks, somthing very simple like this:
private static String readLineFormFile(String filename){
File filepath= new File(filename);
BufferedReader reader = null;
String line =null;
try{
reader = new BufferedReader(new FileReader(filepath));
line=reader.readLine();
}
catch (FileNotFoundException fe1){
System.out.println(filename+" file Not Found");
}
catch (IOException ie1) {
System.out.println("Error Reading File "+filename);
}
finally{
try{
reader.close();
}catch(IOException ie2){
System.out.println("Error closing file "+filename);
}
}
return line;
}
Now if I call this method on a file 2 times, will the buffereader still know the line I was after I close it for the first time?
will the buffereader still [k]now the line i was after i close it for the first time?
No. You will be reading from the beginning of the file each time.
No.
Each time you run the method, a new BufferedReader object is created. When the method ends, the object is destroyed, and a new one is created the next time you run the method.
The information about where you're up to in the reading is stored in the BufferedReader object, and is not shared by all such objects.
What object instance would that be? The BufferedReader instance is created twice; once for each call, using the new keyword on the constructor. reader is a local variable that goes out of scope when the method is exited.
I am trying an example from
http://www.roseindia.net/java/beginners/java-read-file-line-by-line.shtml
in the example the BufferReader is not closed is that necessary to close the BufferReaderor not? Please explain.
FileInputStream fstream = new FileInputStream("textfile.txt");
BufferedReader br = new BufferedReader(new InputStreamReader(fstream));
String strLine;
//Read File Line By Line
while ((strLine = br.readLine()) != null) {
// Print the content on the console
System.out.println (strLine);
}
//Close the input stream
in.close();
Always close streams. It's a good habit which helps you to avoid some odd behaviour. Calling close() method also calls flush() so you don't have do this manually.
The best place where to close streams is probably in a finally block. If you have it like in your example and an exception occurs before the in.close() line, the stream won't be closed.
And if you have chained streams, you can only close the last one and all before it are closed too. This means br.close() in your example - not in.close();
Example
try {
// do something with streams
} catch (IOException e) {
// process exception - log, wrap into your runtime, whatever you want to...
} finally {
try {
stream.close();
} catch (IOException e) {
// error - log it at least
}
}
Alternatively you can use closeQuietly(java.io.InputStream) in Apache Commons library.
From the perspective of resource leak prevention, it is not strictly necessary to close a wrapper stream if you've also closed the stream that it wraps. However, closing the wrapped stream may result in stuff getting lost (specifically in the output case), so it is better to close (just) the wrapper, and rely on documented behavior that the closing the wrapper closes the wrapped stream too. (That is certainly true for the standard I/O wrapper classes!)
Like Peter Lawrey, I question the wisdom of relying on "Rose India" examples. For instance, this one has two more obvious mistakes in it that no half-decent Java programmer should make:
The stream is not closed in a finally block. If any exception is thrown between opening and closing, the in.close() statement won't be executed, and the application will leak an open file descriptor. Do that too often and your application will start throwing unexpected IOExceptions.
The DataInputStream in the chain serves no useful purpose. Instead, they should use fstream as the parameter for the InputStreamReader. Or better still, use FileReader.
Finally, here is a corrected version of the example:
BufferedReader br = new BufferedReader(new FileReader ("textfile.txt"));
try {
String line;
while ((line = br.readLine()) != null) {
// Print the content on the console
System.out.println(line);
}
} finally {
// Close the reader stack.
br.close();
}
or using Java 7's "try with resource":
try (BufferedReader br = new BufferedReader(new FileReader ("textfile.txt"))) {
String line;
while ((line = br.readLine()) != null) {
// Print the content on the console
System.out.println(line);
}
}
Since the underlying stream is closed, it is not absolutely necessary to close BufferedReader, even though it is a good practice to close ALL Closeables in reverse order (relative to the order they were opened in.)