Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Read first line of file with Files.lines in Java

Tags:

java

file-io

I want to use this code to read only the first line from a file:

String line = Files.lines(path).findFirst().get();

I assume that this does NOT load the contents of the entire file into memory. Instead, it opens the file, reads ONLY the first line and then closes the file.

Is my assumption correct?

like image 421
stepanian Avatar asked Jan 05 '18 21:01

stepanian


People also ask

How do you read a specific line from a text file in Java?

Java supports several file-reading features. One such utility is reading a specific line in a file. We can do this by simply providing the desired line number; the stream will read the text at that location. The Files class can be used to read the n t h nth nth line of a file.

What is the easiest way to read text Files line by line in Java 8?

Java 8 has added a new method called lines() in the Files class which can be used to read a file line by line in Java. The beauty of this method is that it reads all lines from a file as Stream of String, which is populated lazily as the stream is consumed.

Which method is used to read file line by line?

We can use java. io. BufferedReader readLine() method to read file line by line to String. This method returns null when end of file is reached.


2 Answers

From the Files Javadoc:

static Stream lines(Path path) - Read all lines from a file as a Stream.

Files.lines(path) reads all lines, meaning they have the potential to be accessed, but what's loaded into memory depends on what's required for the stream. In your case, only the first line will be accessed (stored in memory), since the BufferedReader is able to lazily load contents into memory as necessary.

like image 89
Matt Goodrich Avatar answered Oct 19 '22 03:10

Matt Goodrich


The Files#lines method uses a BufferedReader class to access the lines using BufferedReader#lines. From the source

Returns a Stream, the elements of which are lines read from this BufferedReader. The java.util.stream.Stream is lazily populated, i.e., read only occurs during the terminal stream operation. The reader must not be operated on during the execution of the terminal stream operation. Otherwise, the result of the terminal stream operation is undefined.

After execution of the terminal stream operation there are no guarantees that the reader will be at a specific position from which to read the next character or line.

If an IOException is thrown when accessing the underlying BufferedReader, it is wrapped in an UncheckedIOException which will be thrown from the Stream method that caused the read to take place. This method will return a Stream if invoked on a BufferedReader that is closed. Any operation on that stream that requires reading from the BufferedReader after it is closed, will cause an UncheckedIOException to be thrown.

public Stream<String> lines() {
    Iterator<String> iter = new Iterator<String>() {
        String nextLine = null;

        @Override
        public boolean hasNext() {
            if (nextLine != null) {
                return true;
            } else {
                try {
                    nextLine = readLine();
                    return (nextLine != null);
                } catch (IOException e) {
                    throw new UncheckedIOException(e);
                }
            }
        }

        @Override
        public String next() {
            if (nextLine != null || hasNext()) {
                String line = nextLine;
                nextLine = null;
                return line;
            } else {
                throw new NoSuchElementException();
            }
        }
    };
    return StreamSupport.stream(Spliterators.spliteratorUnknownSize(
            iter, Spliterator.ORDERED | Spliterator.NONNULL), false);
}

The Stream created by StreamSupport.stream is backed by an Iterator. The stream is only asked for one element because you call Stream#findFirst. Therefore only one call to hasNext and next are made, meaning that BufferedReader#readLine is only called once.

like image 32
flakes Avatar answered Oct 19 '22 04:10

flakes