I have a class where on the one hand, it feels right to return an InputStream
from a public method, e.g.
public class MyClass {
private File _file;
...
public InputStream getInputStream() {
return new FileInputStream( _file );
}
}
However, I'm also very cautious about doing this, as it puts the onus on the caller to close this stream. What ways can I potentially avoid this problem?
Depends on why this is a problem in your eyes. If you absolutely must return an InputStream
and the file in question is not too large, you could buffer the entire file into a byte array, close the original stream and return new ByteArrayInputStream(buf)
. Closing a ByteArrayInputStream
is not necessary (and in fact has no effect).
However, if it "feels right" to return an InputStream
, does it not make sense that the caller should be expecting an InputStream
, and all that goes with it, including the necessity of closing the stream when finished?
Returning InputStream
is not intrinsically a bad thing. Now if you want your caller to access the data without being responsible for closing the resource, you can do that:
interface InputReader {
void readInput(InputStream is);
}
public class MyClass {
void feed(InputReader ir){
try(InputStream is=new FileInputStream( _file )){
ir.readInput(is);
}
}
}
The caller specify an instance of InputReader
that will receive the closable resource as argument and is no longer responsible for closing it.
MyClass myClass = ... ; //Get the instance
myClass.feed( new InputReader() {
@Override
void readInput(InputStream is){
... ; // Use at will without closing
}
});
One should consider to decorate the InputStream
before passing it to the InputReader
so that .close()
throws and exception.
Realistically there's not much you can do without knowing more details about the class. You could provide file processing through methods in MyClass (which requires knowing what the file contents mean) and close the stream when it's empty. Aside from that though, the user of the class is responsible for this object, and you can't really avoid that. Without the capability of destructors, as in C++, you cannot be 100% responsible for any object that you let leave the scope of your class.
What you can do is put a close()
method on your class which cleans up any open file handlers, connections, etc., and require the user of the class to be responsible for calling close()
. See this question for some discussion of how to use the finalize
method to keep track of whether callers are properly closing your class.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With