Manuel Jordan Manuel Jordan -4 years ago 56
Java Question

Java 8: Supplier working with files throws "stream has already been operated upon or closed"

Working with

JUnit
and
Stream
I have the following error message:

java.lang.IllegalStateException: stream has already been operated upon or closed


I did a research, and is clear is not possible reuse a stream

But according with this post:



working with
Supplier
is possible work around with this problem.

So my current code is the following:

try (Stream<String> stream = Files.lines(Paths.get(fileName)) ) {

Supplier<Stream<String>> supplier = () -> stream;

logger.info("A");
logger.info("ABC {}", supplier.get().findFirst().get());
logger.info("B");
logger.info("XYZ {}", supplier.get().skip(1050).findFirst().get());
logger.info("C");

assertThat(supplier.get().count(), is(1051));

}
catch (IOException e) {
logger.error("{}", e.getMessage());
}


How you can see I use the
supplier.get()
to work with the
Stream
(it according with the tutorial), but the
@Test
prints until B, therefore the
@Test
fails in
supplier.get().skip(1050).findFirst().get()
and it is still generating the same error message.

The unique difference between my code and the tutorial, the mime works through a File and the tutorial works around an array.

Something special to edit to work without any problem?

Alpha

I did the following edition (according with the snippet code of Eugene)

try (Stream<String> stream = Files.lines(Paths.get(fileName)) ) {

Supplier<Stream<String>> supplier = () -> stream.collect(Collectors.toList()).stream();

logger.info("A");
logger.info("ABC {}", supplier.get().findFirst().get());
logger.info("B");
logger.info("XYZ {}", supplier.get().skip(1050).findFirst().get());
logger.info("C");

assertThat(supplier.get().count(), is(1051));

}


Same error message.

Answer Source

Supplier is no magic, you still need to provide a new Stream all the time from that Supplier.

So you could do:

Supplier<Stream<String>> supplier = () -> Files.lines(Paths.get(fileName));

But that would mean to read the file, all the time. You could read all the lines into a single List, store that in memory and stream out of that.

List<String> allLines = Files.readAllLines(Paths.get(fileName));

Supplier<Stream<String>> supplier = () -> allLines.stream();

Notice that even the tutorial that you have linked returns a new Stream, created via Stream.of like so:

 Supplier<Stream<String>> streamSupplier = () -> Stream.of(array);
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download