Closing a closed Stream has no effect
how to prevent the developers from touching the method additionalMethod()
from closing the resource by mistake?
Maybe passing around closeable resources is not a good idea at all.
Maybe passing around closeable resources is not a good idea at all.
There's nothing bad with opening the stream in one method, where it's wrapped in try-with-resources in handing it out to another method, like in your example.
If you call close()
on a stream multiple times, nothing would fail. The first call would close the stream, the subsequent calls would have no effect.
Here's a quote from the documentation of the Reader
interface:
Closes the stream and releases any system resources associated with it. Once the stream has been closed, further read()
, ready()
, mark()
, reset()
, or skip()
invocations will throw an IOException. Closing a previously closed stream has no effect.
BufferedReader vs Scanner
Hovewhever, using Scanner
for dialing with files is not the most performant approach, you can use FileReader
wrapped with a BufferedReader
which has a greater capacity of the buffer than Scanner (8192
vs 1024
).
public void readMethod(String fileName) {
try (var reader = new BufferedReader(new FileReader(fileName))) {
additionalMethod(reader);
} catch (IOException e) {
e.printStackTrace();
}
}
public void additionalMethod(BufferedReader reader) throws IOException {
String line = null;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
reader.close(); // it's pointless but not harmful
reader.close(); // it's pointless but not harmful
}
NIO.2
Methods for handling Input/Output became way learner if you're using NIO.2 API.
That how these two methods could be reimplemented using [Files.lines()
] which produces a stream of lines:
public void readMethod(String fileName) {
try (Stream<String> stream = Files.lines(Path.of(fileName), Charset.defaultCharset())) {
additionalMethod(stream);
} catch (IOException e) {
e.printStackTrace();
}
}
public void additionalMethod(Stream<String> stream) {
stream.forEach(System.out::println);
}