There are plenty of similar questions that have been answered. Example here. However, they all have both the Reader and the InputStream within the same scope or method body, and so suggest to close the last in the chain (Reader
) instead of the first (InputStream
).
So for my particular case, I am building an API, and want the users to give a choice of which input source to use. They need flexibility. For this I typically follow this type of template:
public class Handler {
public void handle(BufferedReader in) {
in.lines().forEach(System.out::println);
}
public void handle(InputStream in) {
handle(new BufferedReader(new InputStreamReader(in)));
}
public void handle(Class anchor,String resource) throws IOException {
try (InputStream in = anchor.getResourceAsStream(resource)) {
handle(in);
}
}
public void handle(String resource) throws IOException {
try (InputStream in = ClassLoader.getSystemResourceAsStream(resource)) {
handle(in);
}
}
public void handle(Path path) throws IOException {
try (InputStream in = Files.newInputStream(path)) {
handle(in);
}
}
public void handle(File file) throws IOException {
try (InputStream in = Files.newInputStream(file.toPath())) {
handle(in);
}
}
public static void main(String args[]) throws NoSuchMethodException, IOException {
Handler h = new Handler();
h.handle(Handler.class,"/readme.txt");
}
}
I think it has following benefits:
- Only the owner of he resource can close it. In the case of reader/input, the benefit is not so clear. However, if it would have been writer/output, then this would have allowed me to have several such functions operate consecutively after each other on the same resource. I think that makes sense as an API.
- Simple to understand: if you pass/own the resource, you have the responsibility of closing it.
- If you pass along a resource name (
String
), it is clear that the api will have to take care of both opening and closing the resource.
So there is a difference with the other postings, both in situation, and how to answer it:
- Here: if
Reader
orInputStream
gets passed as a parameter to a method of an API, then do not.close()
on it inside the API method body. - Others: if within the same scope,
InputStream
is chained with aReader
, then always close the last in the chain (theReader
).
I think this makes sense, but is this a correct way of handling this?
Reader
s andInputStream
s should be treated the same, as basically their only difference is characters versus bytes.