Search code examples
javajava-stream

IllegalStateException occurs, writing a stream


What am I doing wrong here:

private static void writeAllTxtSorted(String fileId) {
    try {
        Path file = tmp.resolve("AllTxt" + fileId);
        Files.deleteIfExists(file);
69->    Files.write(file, find().sorted()::iterator, StandardOpenOption.CREATE);
    } catch (Exception e) {
        err(e, "problems", l);
    }
}

static Stream<CharSequence> find() throws IOException {
    try (Stream<Path> walk = Files.walk(Path.of("C:/Temp"))) {
        return walk.map(pth -> pth.toString());
    }
}
java.lang.IllegalStateException null
[java.base/java.nio.file.FileTreeIterator.hasNext(FileTreeIterator.java:102)
    java.base/java.util.Spliterators$IteratorSpliterator.tryAdvance(Spliterators.java:1855)
    java.base/java.util.stream.StreamSpliterators$WrappingSpliterator.lambda$initPartialTraversalState$0(StreamSpliterators.java:292)
    java.base/java.util.stream.StreamSpliterators$AbstractWrappingSpliterator.fillBuffer(StreamSpliterators.java:206)
    java.base/java.util.stream.StreamSpliterators$AbstractWrappingSpliterator.doAdvance(StreamSpliterators.java:161)
    java.base/java.util.stream.StreamSpliterators$WrappingSpliterator.tryAdvance(StreamSpliterators.java:298)
    java.base/java.util.Spliterators$1Adapter.hasNext(Spliterators.java:681)
    java.base/java.nio.file.Files.write(Files.java:3583)
    java.base/java.nio.file.Files.write(Files.java:3633)
    eu.ngong.allTxt/eu.ngong.allTxt.App.writeAllTxtSorted(App.java:69)
    eu.ngong.allTxt/eu.ngong.allTxt.App.main(App.java:50)]

tmp is java.io.temp.
err is an operation logging the error on the Logger l.

What this reduced code should do is, write all paths of files below C:\Temp to a file.
Instead it throws the exception IllegalStateException.


Solution

  • Don't close the Stream<Path> returned by walk inside the find method (as is currently being done by the try-with-resources).

    According to the documentation (emphasis mine):

    The returned stream contains references to one or more open directories. The directories are closed by closing the stream.

    API Note: This method must be used within a try-with-resources statement or similar control structure to ensure that the stream's open directories are closed promptly after the stream's operations have completed.

    static Stream<CharSequence> find() throws IOException {
        return Files.walk(Path.of("C:/Temp")).map(Path::toString);
    }
    

    You can close it in writeAllTxtSorted instead.

    try (var walk = find().sorted()) {
        Files.write(file, walk::iterator, StandardOpenOption.CREATE);
    }