Java java.nio.file.Files.lines()
方法
Files.lines()
方法是 Java 8 引入的一个静态方法,位于 java.nio.file.Files
类中。它的主要作用是将文件内容作为字符串流(Stream<String>
)返回,其中每个字符串代表文件中的一行。
方法定义
public static Stream<String> lines(Path path) throws IOException
public static Stream<String> lines(Path path, Charset cs) throws IOException
public static Stream<String> lines(Path path, Charset cs) throws IOException
方法有两个重载版本:
- 第一个版本使用默认字符集(UTF-8)读取文件
- 第二个版本允许指定字符集
核心特性
1. 惰性求值(Lazy Evaluation)
lines()
方法返回的是一个流(Stream),这意味着它是惰性求值的。文件不会一次性全部加载到内存中,而是按需读取,这对于处理大文件特别有利。
2. 自动资源管理
当流操作完成后(无论是正常结束还是异常中断),流会自动关闭底层文件资源。不过最佳实践仍然是使用 try-with-resources 语句来确保资源被正确释放。
3. 行终止符处理
方法会自动识别不同的行终止符:
\n
(Unix/Linux)\r\n
(Windows)\r
(旧版 Mac)
基本用法
示例 1:简单读取文件
实例
import java.nio.file.*;
import java.io.IOException;
import java.util.stream.Stream;
public class FilesLinesExample {
public static void main(String[] args) {
Path path = Paths.get("example.txt");
try (Stream<String> lines = Files.lines(path)) {
lines.forEach(System.out::println);
} catch (IOException e) {
e.printStackTrace();
}
}
}
import java.io.IOException;
import java.util.stream.Stream;
public class FilesLinesExample {
public static void main(String[] args) {
Path path = Paths.get("example.txt");
try (Stream<String> lines = Files.lines(path)) {
lines.forEach(System.out::println);
} catch (IOException e) {
e.printStackTrace();
}
}
}
示例 2:使用指定字符集
实例
try (Stream<String> lines = Files.lines(path, StandardCharsets.ISO_8859_1)) {
lines.filter(line -> !line.isEmpty())
.forEach(System.out::println);
} catch (IOException e) {
e.printStackTrace();
}
lines.filter(line -> !line.isEmpty())
.forEach(System.out::println);
} catch (IOException e) {
e.printStackTrace();
}
高级用法
1. 与 Stream API 结合
实例
// 统计非空行数
long count = Files.lines(path)
.filter(line -> !line.trim().isEmpty())
.count();
// 查找包含特定单词的行
List<String> targetLines = Files.lines(path)
.filter(line -> line.contains("important"))
.collect(Collectors.toList());
long count = Files.lines(path)
.filter(line -> !line.trim().isEmpty())
.count();
// 查找包含特定单词的行
List<String> targetLines = Files.lines(path)
.filter(line -> line.contains("important"))
.collect(Collectors.toList());
2. 并行处理
实例
// 并行处理文件行
Files.lines(path)
.parallel()
.map(String::toUpperCase)
.forEachOrdered(System.out::println);
Files.lines(path)
.parallel()
.map(String::toUpperCase)
.forEachOrdered(System.out::println);
注意事项
资源管理:虽然流会自动关闭,但在复杂的流操作中,显式使用 try-with-resources 仍是推荐做法。
性能考虑:对于小文件,
Files.readAllLines()
可能更简单;但对于大文件,lines()
是更好的选择。字符集问题:如果文件编码与系统默认编码不同,务必指定正确的字符集,否则可能读取乱码。
异常处理:IO 操作可能抛出异常,需要妥善处理。
性能比较
方法 | 特点 | 适用场景 |
---|---|---|
Files.lines() |
惰性加载,内存效率高 | 大文件处理 |
Files.readAllLines() |
一次性加载所有行到内存 | 小文件处理 |
BufferedReader.readLine() |
传统方式,手动控制 | 需要精细控制时 |
总结
Files.lines()
方法结合了 Java 8 的 Stream API 和 NIO 的高效文件处理能力,为文件读取提供了现代化、简洁的解决方案。它特别适合处理大文件和执行复杂的行级操作。掌握这个方法可以显著提高文件处理代码的可读性和效率。
在实际开发中,根据文件大小、处理需求和性能要求,合理选择 lines()
、readAllLines()
或传统 IO 方法,才能写出最优的文件处理代码。
点我分享笔记