使用Java中的Files.lines读取第一行文件

ste*_*ian 4 java file-io

我想使用此代码只读取文件中的第一行:

String line = Files.lines(path).findFirst().get();
Run Code Online (Sandbox Code Playgroud)

我假设这不会将整个文件的内容加载到内存中.相反,它打开文件,只读取第一行,然后关闭文件.

我的假设是否正确?

Mat*_*ich 6

Files Javadoc:

static Stream lines(Path path) - 从文件中读取所有行作为Stream.

Files.lines(path)读取所有行,意味着它们有可能被访问,但是加载到内存中的内容取决于流所需的内容.在您的情况下,只有第一行将被访问(存储在内存中),因为BufferedReader它可以根据需要懒惰地将内容加载到内存中.


fla*_*kes 5

Files#lines方法使用BufferedReader类来访问BufferedReader#lines。从源头

返回一个Stream,其元素是从此BufferedReader中读取的行。延迟填充java.util.stream.Stream,即在终端流操作期间仅发生只读操作。在执行终端流操作期间,不得对阅读器进行操作。否则,终端流操作的结果是不确定的。

在执行终端流操作之后,不能保证阅读器将处于从中读取下一个字符或行的特定位置。

如果在访问基础BufferedReader时抛出IOException,则它将包装在UncheckedIOException中,该异常将从导致进行读取的Stream方法中抛出。如果在已关闭的BufferedReader上调用,则此方法将返回Stream。在关闭该流后,需要从BufferedReader读取该流上的任何操作,都将引发UncheckedIOException。

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);
}
Run Code Online (Sandbox Code Playgroud)

Stream创建,StreamSupport.streamIterator。因为您调用,所以仅向流要求一个元素Stream#findFirst。因此,仅对hasNextnext进行一次调用,这意味着BufferedReader#readLine仅被调用一次。