Java 8:使用文件的供应商抛出“流已经被操作或关闭”

时间:2017-06-12 18:09:07

标签: java java-8 java-stream

使用JUnitStream我收到以下错误消息:

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

我做了一项研究,很清楚可能重用流

但是根据这篇文章:

使用Supplier可以解决此问题。

所以我目前的代码如下:

    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());
    }

如何看待我使用supplier.get()使用Stream根据教程),但@Test打印直到 B ,因此@Testsupplier.get().skip(1050).findFirst().get()失败,但仍然会生成相同的错误消息。

我的代码和教程之间的独特区别,mime通过文件工作,教程围绕数组工作。

编辑工作没有任何问题?

α

我做了以下版本(根据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));

    }

相同的错误消息。

2 个答案:

答案 0 :(得分:7)

Supplier并不神奇,您仍然需要始终从该供应商提供 new Stream

所以你可以这样做:

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

但这意味着要一直读取文件。您可以将所有行读入单个List,将其存储在内存中,并将stream存储在内存中。

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

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

请注意,即使您链接的教程也会返回一个新的Stream,通过Stream.of创建,如下所示:

 Supplier<Stream<String>> streamSupplier = () -> Stream.of(array);

答案 1 :(得分:3)

这是因为您的供应商始终提供Stream的相同实例,并且您已使用findFirst()使用它。然后你尝试用findFirst()再次使用它,这是不允许的。

在本教程中,每次都会创建一个新流。在您的情况下,您必须在供应商内部调用Files.lines()才能使其正常工作,但这意味着您每次都会重新阅读该文件。

相关问题