Try-with transfer ownership - java

In Java 7, there is a try-with syntax that ensures objects like InputStream are closed in all code paths, regardless of exceptions. However, the variable declared in the try-with block ("is") is final.
try (InputStream is = new FileInputStream("1.txt")) {
// do some stuff with "is"
is.read();
// give "is" to another owner
someObject.setStream(is);
// release "is" from ownership: doesn't work because it is final
is = null;
}
Is there a concise syntax to express this in Java? Consider this exception-unsafe method. Adding the relevant try/catch/finally blocks would make the method much more verbose.
InputStream openTwoFiles(String first, String second)
{
InputStream is1 = new FileInputStream("1.txt");
// is1 is leaked on exception
InputStream is2 = new FileInputStream("2.txt");
// can't use try-with because it would close is1 and is2
InputStream dual = new DualInputStream(is1, is2);
return dual;
}
Obviously, I can have the caller open both files, placing them both in a try-with block. This is only one example of a case where I want to perform some operation on a resource before transferring ownership of it to another object.

The try-with is intended to be used in a situation where the identified resource must never persist outside the scope of the try block.
If you want to use the try-with construction, you must change your design as follows:
Delete the openTwoFiles() method. it is value free.
Create a constructor for the DualInputStream class that takes two file names and creates the two InputStreams. Declare that this constructor throws IOException and allow it to throw IOExceptions.
Use the new constructor in a try-with construct.

Related

How to write test case readFile method which return type is void

I am new in writing test cases, Please help me for writing test case for below methods . Thanks in advance!!
public void readFile() throws IOException{
linesProcessed = 0;
FileInputStream fileInStream = new FileInputStream(filePath);
DataInputStream dataInStream = new DataInputStream(fileInStream);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(dataInStream));
String strLine;
fileData.clear();
while(StringUtils.isNotBlank((strLine = bufferedReader.readLine()))) {
++linesProcessed;
processLine(strLine);
}
bufferedReader.close();
dataInStream.close();
fileInStream.close();
}
Many things to say here.
First of all, to answer your question. When a method doesn't return something, you can still can check whether some "other state" gets updated accordingly.
In your case, one meaningful point of observation could be that call
processLine(strLine);
In other words: you could see what that method is doing, and somehow verify that the other method was called as you would expect it.
Then: you actually wrote hard-to-test code. One reason for that is because this method starts its work on a string (that points to a file). Instead, you could pass a reader object to that method already. Then there wouldn't be a need to use PowerMock for example. You simply prepare a reader object that has known content, and then you can verify that actions follow that match that prepared content!
Beyond that, you should learn about try-with-resources, and you should also study more how to do IO. There is no point in closing all 3 streams. When you create a reader on some other stream, and you close the outer reader, that "base" stream gets closed automatically along the way.

The Properties.load would close the InputStream?

I saw this example, and I didn't see the close() method invoked on the InputStream, so would prop.load() close the stream automatically? Or is there a bug in the example?
The Stream is not closed after Properties.load ()
public static void main(String[] args) throws IOException {
InputStream in = new FileInputStream(new File("abc.properties"));
new Properties().load(in);
System.out.println(in.read());
}
The above code returns "-1" so the stream is not closed. Otherwise it should have thrown java.io.IOException: Stream Closed
Why do you ask when the javadoc of Properties.load(InputStream inStream) says this?
The specified stream remains open after this method returns.
It has been saying that since Java 6.
As EJP said in a comment: Don't rely on arbitrary Internet junk. Use the official Oracle Java documentation as your primary source of information.
The following try-with-resources will close the InputStream automatically (you can add catch and finally if needed):
try (InputStream is = new FileInputStream("properties.txt")) {
// is will be closed automatically
}
Any resource declared within a try block opening will be closed. Hence, the new construct shields you from having to pair try blocks with corresponding finally blocks that are dedicated to proper resource management.
Article by Oracle here: http://www.oracle.com/technetwork/articles/java/trywithresources-401775.html.

Reusing the input stream variable

Consider the following code snippet getInputStreamForRead() method creates and returns a new input stream for read.
InputStream is = getInputStreamForRead(); //This method creates and returns an input stream for file read
is = getDecompressedStream(is);
Since the orginal file content is compressed and stored it has to be decompressed while reading. Hence getDecompressedStream() method below would provide option to decompress the stream content
public InputStream getDecompressedStream(InputStream is) throws Exception {
return new GZIPInputStream(is);
}
Have the following doubts
Which one is correct for the above snippet
is = getDecompressedStream(is)
or
InputStream newStream = getDecompressedStream(is)
Will reusing the InputStream variable again cause any trouble?
I'm completely new with streams. Kindly help me to know about this.
As long as:
you're not manipulating the original InputStream between the original assignment and the new invocation
you're always closing your streams in a finally statement
... you should be fine re-assigning to the original variable - it's just a new value passed to an existing reference.
In fact, that may be the recommended way, since you get to only close one Closeable programmatically, as GZIPInputStream#close...
Closes this input stream and releases any system resources associated with the stream.
(see here - I read this as, "closes the underlying stream").
Since you want to close the input stream correctly, the best way is to create the input stream using chaining, and using a try-with-resources to handle the close for you.
try (InputStream is = getDecompressedStream(getInputStreamForRead())) {
// code using stream here
}

Closing a BufferedReader

If I invoke a BufferedReader the following way:
Integer.parseInt(new BufferedReader(new InputStreamReader(System.in)).readLine());
Will the JVM know to automatically close it when not in use? If not, how do I go about closing it?
If you are using java 7 or greater and your code is in try catch resource block, then it is Auto closes.
If in below versions you have to close with close(). For that you have to change your current way of using and get the reference.
Don't chain them, declare and assign variables, then close it after the usage.
InputStreamReader isReader;
BufferedReader bfReader;
try {
isReader = new InputStreamReader(System.in);
bfReader = new BufferedReader(isReader).readLine();
} catch (Exception e) {
// handle as per the requirement.
} finally {
bfReader.close();
}
If you use java 7, then, if you defined withing the try clause, then those will auto closable. Check here for more details
The try-with-resources statement is a try statement that declares one
or more resources. A resource is as an object that must be closed
after the program is finished with it. The try-with-resources
statement ensures that each resource is closed at the end of the
statement. Any object that implements java.lang.AutoCloseable, which
includes all objects which implement java.io.Closeable, can be used as
a resource.

How to find out which thread is locking a file in java?

I'm trying to delete a file that another thread within my program has previously worked with.
I'm unable to delete the file but I'm not sure how to figure out which thread may be using the file.
So how do I find out which thread is locking the file in java?
I don't have a straight answer (and I don't think there's one either, this is controlled at OS-level (native), not at JVM-level) and I also don't really see the value of the answer (you still can't close the file programmatically once you found out which thread it is), but I think you don't know yet that the inability to delete is usually caused when the file is still open. This may happen when you do not explicitly call Closeable#close() on the InputStream, OutputStream, Reader or Writer which is constructed around the File in question.
Basic demo:
public static void main(String[] args) throws Exception {
File file = new File("c:/test.txt"); // Precreate this test file first.
FileOutputStream output = new FileOutputStream(file); // This opens the file!
System.out.println(file.delete()); // false
output.close(); // This explicitly closes the file!
System.out.println(file.delete()); // true
}
In other words, ensure that throughout your entire Java IO stuff the code is properly closing the resources after use. The normal idiom is to do this in the try-with-resources statement, so that you can be certain that the resources will be freed up anyway, even in case of an IOException. E.g.
try (OutputStream output = new FileOutputStream(file)) {
// ...
}
Do it for any InputStream, OutputStream, Reader and Writer, etc whatever implements AutoCloseable, which you're opening yourself (using the new keyword).
This is technically not needed on certain implementations, such as ByteArrayOutputStream, but for the sake of clarity, just adhere the close-in-finally idiom everywhere to avoid misconceptions and refactoring-bugs.
In case you're not on Java 7 or newer yet, then use the below try-finally idiom instead.
OutputStream output = null;
try {
output = new FileOutputStream(file);
// ...
} finally {
if (output != null) try { output.close(); } catch (IOException logOrIgnore) {}
}
Hope this helps to nail down the root cause of your particular problem.
About this question, I also try to find out this answer, and ask this question and find answer:
Every time when JVM thread lock a file exclusively, also JVM lock
some Jave object, for example, I find in my case:
sun.nio.fs.NativeBuffer
sun.nio.ch.Util$BufferCache
So you need just find this locked Java object and analyzed them and
you find what thread locked your file.
I not sure that it work if file just open (without locked exclusively), but I'm sure that is work if file be locked exclusively by Thread (using java.nio.channels.FileLock, java.nio.channels.FileChannel and so on)
More info see this question

Categories