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
}
Related
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'm still learning Java and I need some help understanding why this code is wrong:
BufferedReader infile = new BufferedReader(new FileReader(file));
String regel = infile.readLine();
while (regel != null) {
// Do something with regel.
regel = infile.readLine();
}
infile.close();
I really don't see the problem but Eclipse keeps telling there is a resource leak and that infile isn't closed.
(one more detail, this code stands in a try block but I left it away to keep it simple)
Eclipse is complaining because the reference may not be closed (for example, in an Exception); this is where you would use a finally block - perhaps like so
BufferedReader infile = null;
try {
infile = new BufferedReader(new FileReader(file));
String regel = infile.readLine();
while (regel != null) {
// Do something with regel.
regel = infile.readLine();
}
} catch (Exception e) {
e.printStackTrace(); // Log the exception.
} finally {
if (infile != null) {
infile.close(); // close the resource.
}
}
You should have a try/catch block.
Also you should use the following instead:
while ((line = reader.readLine()) != null) {
//do something with line;
}
I think Elliott Frisch is correct and pointed out the main reason the only thing I would add is You should close the stream (in a finally block) because to ensure that any output buffers are flushed in the case that output was otherwise successful. If the flush fails, the code should exit via an exception. Here is another example similar to what you are trying to solve and make sure you look at (Guideline 1-2: Release resources in all cases) http://www.oracle.com/technetwork/java/seccodeguide-139067.html
final OutputStream rawOut = new FileOutputStream(file);
try {
final BufferedOutputStream out =
new BufferedOutputStream(rawOut);
use(out);
out.flush();
} finally {
rawOut.close();
}
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.
I have a network drive at school, I have the ability to read and write to it normally, but when I use java to take an existing text file and try and write to it, I get this exception:
java.io.FileNotFoundException: p:\CompSci_CheckIn_Name.txt (The process cannot access the file because it is being used by another process)
I can read it just fine and all but when I try and write to it, it throws me an exception. I can write to my desktop and read and everything from my desktop but when I try my network drive, it gives up. How could I get around this problem?
Reading
file = new File(directories[i], "CompSci_CheckIn_Name.txt");
readName = new BufferedReader(new FileReader(file));
userName = readName.readLine();
passed = true;
Writing
write = new PrintWriter(file);
write.println(newUser);
write.flush();
userName = newUser;
write.close();
I have already tried a BufferedWriter with no luck, same result.
You should close() BufferedReader and FileReader after using them.
Use a try/finally block and close your Readers in the finally block.
FileReader fr = null;
BufferdReader br = null;
try {
fr = new FileRader(file);
br = new BufferedReader(fr);
// do something..
} finally {
if (br != null) br.close();
if (fr != null) fr.close();
}