我想要使用这个代码只读取文件的第一行:
String line = Files.lines(path).findFirst().get();
我认为这种方法不会将整个文件的内容加载到内存中,而是打开文件,只读取第一行内容,然后关闭文件。
我的假设是正确的吗?
来自文件Javadoc:
static Stream lines(Path path) - 将文件中的所有行读取为流。
Files.lines(path)
会读取所有行,这意味着它们有可能被访问,但是加载到内存中的内容取决于流所需的内容。在你的情况下,只有第一行将被访问(存储在内存中),因为BufferedReader
能够按需惰性地加载内容到内存中。
Files#lines
方法使用 BufferedReader
类来访问行,使用 BufferedReader#lines
来获取行。从 源代码 可知:
返回一个流,其元素是从此 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);
}
StreamSupport.stream
创建的Stream
是由一个Iterator
支持的。因为你调用了Stream#findFirst
,所以只要求一个元素。因此,仅调用一次hasNext
和next
,这意味着BufferedReader#readLine
仅被调用一次。请保留HTML标记。