learner
learner

Reputation: 316

Second call to "get" method of Supplier is empty

For the below code, if I make a second call to supplier with "get" method, the count is zero.

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Scanner;
import java.util.function.Supplier;
import java.util.stream.Stream;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class FileOperations {

    private Logger logger = LoggerFactory.getLogger(getClass());

    public static void main(String[] args) {
        FileOperations fOps = new FileOperations();

        fOps.usingBufferedReader();

    }

    public void usingBufferedReader() {
        Path path = Path.of("app_log.log");
        
        /**
         * Only first operation with stream provide results.
         */
        try (BufferedReader reader = Files.newBufferedReader(path);) {
            Supplier<Stream<String>> streamSupplier = () -> reader.lines();
            
            streamSupplier.get().forEach(ln -> {
                System.out.println(ln);                 // Prints all lines properly
            });
            
            long count = streamSupplier.get().count();
            System.out.println("count = " + count);     // Outputs "0"
        } catch (IOException e) {
            logger.error("IOException: %s%n", e);
        }
    }
}

I tried having count as first call to streamSupplier.get.

long count = streamSupplier.get().count();
System.out.println("count = " + count);     // Outputs "0"

At that time it properly printed the count as 528, but didn't printed the lines of the file.

I'm using Java 17

Upvotes: 0

Views: 62

Answers (1)

Rob Spoor
Rob Spoor

Reputation: 9100

DuncG gave the correct answer in his comment, but let me go a bit deeper.

reader.lines() returns a new stream over the lines of the reader. Like any stream it doesn't do anything until a terminal operation is called. When you call forEach the stream will start reading lines, either using readLine() in the background or doing something similar. Either way it will read all content from the reader. When the stream is done the reader's content has been consumed; calling reader.read() will return -1.

When you call the supplier again, reader.lines() returns a new stream. But like DuncG said, the backing reader hasn't been reset, all of its content still has been consumed, and the result is that no lines are available - the stream is empty.

Upvotes: 5

Related Questions