news 2026/4/23 16:50:04

Java 一行一行的读取文本,小Demo 大学问

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java 一行一行的读取文本,小Demo 大学问

String str="A\n" +

"B\n" +

"C";

在Java中,有多种方式可以一行一行地读取文本。以下是几种常用的方法:

1. 使用 BufferedReader + FileReader

String str = "A\n" + "B\n" + "C";

// 方法1:从字符串读取

try (BufferedReader reader = new BufferedReader(new StringReader(str))) {

String line;

while ((line = reader.readLine()) != null) {

System.out.println(line);

}

} catch (IOException e) {

e.printStackTrace();

}

// 方法2:从文件读取

try (BufferedReader reader = new BufferedReader(new FileReader("filename.txt"))) {

String line;

while ((line = reader.readLine()) != null) {

System.out.println(line);

}

} catch (IOException e) {

e.printStackTrace();

}

2. 使用 Scanner

String str = "A\n" + "B\n" + "C";

// 从字符串读取

try (Scanner scanner = new Scanner(str)) {

while (scanner.hasNextLine()) {

String line = scanner.nextLine();

System.out.println(line);

}

}

// 从文件读取

try (Scanner scanner = new Scanner(new File("filename.txt"))) {

while (scanner.hasNextLine()) {

String line = scanner.nextLine();

System.out.println(line);

}

} catch (FileNotFoundException e) {

e.printStackTrace();

}

3. 使用 Files.lines() (Java 8+)

String str = "A\n" + "B\n" + "C";

// 从字符串读取(需要先写入临时文件)

try {

Path tempFile = Files.createTempFile("temp", ".txt");

Files.write(tempFile, str.getBytes());

Files.lines(tempFile).forEach(System.out::println);

// 清理临时文件

Files.deleteIfExists(tempFile);

} catch (IOException e) {

e.printStackTrace();

}

// 从文件读取

try {

Files.lines(Paths.get("filename.txt")).forEach(System.out::println);

} catch (IOException e) {

e.printStackTrace();

}

4. 使用 String 的 split() 方法(适用于字符串)

String str = "A\n" + "B\n" + "C";

String[] lines = str.split("\n");

for (String line : lines) {

System.out.println(line);

}

//处理空行

String[] lines = str.split("\\r?\\n|\\r");

List<String> nonEmptyLines = Arrays.stream(lines)

.filter(line -> !line.trim().isEmpty())

.collect(Collectors.toList());

5. 使用 Lines() 方法 (Java 11+)

String str = "A\n" + "B\n" + "C";

// 从字符串读取

str.lines().forEach(System.out::println);

推荐方案

对于字符串:使用 str.lines() (Java 11+) 或 split("\n")

对于文件:使用 Files.lines() (Java 8+) 或 BufferedReader

需要更多控制:使用 Scanner

最简洁的方式是使用 Java 11 的 lines() 方法:

String str = "A\n" + "B\n" + "C";

str.lines().forEach(System.out::println);

输出结果:

A

B

C

在 Java 8 环境下,split("\n") 和 BufferedReader 各有优缺点,具体选择取决于使用场景:

性能对比

1. split("\n") - 适用于小文本

String str = "A\n" + "B\n" + "C";

String[] lines = str.split("\n");

for (String line : lines) {

System.out.println(line);

}

优点:

代码简洁,一行搞定

适合已知内容较小的字符串

可以直接得到数组,方便后续处理

缺点:

一次性加载所有内容到内存,大文本会占用大量内存

需要处理尾部的空行问题

2. BufferedReader - 适用于大文本或文件

String str = "A\n" + "B\n" + "C";

try (BufferedReader reader = new BufferedReader(new StringReader(str))) {

String line;

while ((line = reader.readLine()) != null) {

System.out.println(line);

}

} catch (IOException e) {

e.printStackTrace();

}

优点:

内存效率高,逐行读取,适合大文件

自动处理不同操作系统的换行符(\n, \r\n, \r)

统一的接口处理字符串和文件

缺点:

代码相对冗长

需要处理异常

推荐选择

场景 1:小文本,内容已知且不大

// 使用 split("\n")

String[] lines = str.split("\n");

Arrays.stream(lines).forEach(System.out::println);

场景 2:大文本或需要处理文件

// 使用 BufferedReader

try (BufferedReader reader = new BufferedReader(new StringReader(str))) {

reader.lines().forEach(System.out::println); // Java 8 Stream API

} catch (IOException e) {

e.printStackTrace();

}

场景 3:Java 8 更优雅的写法

// 结合 BufferedReader 和 Stream API

try (BufferedReader reader = new BufferedReader(new StringReader(str))) {

List<String> lines = reader.lines().collect(Collectors.toList());

lines.forEach(System.out::println);

} catch (IOException e) {

e.printStackTrace();

}

实际建议

对于你的具体案例:

String str = "A\n" + "B\n" + "C";

// 如果确定文本很小,用 split 更简洁

String[] lines = str.split("\n");

for (String line : lines) {

System.out.println(line);

}

// 如果要养成好习惯或处理可能的大文本,用 BufferedReader

try (BufferedReader reader = new BufferedReader(new StringReader(str))) {

reader.lines().forEach(System.out::println);

} catch (IOException e) {

e.printStackTrace();

}

总结: 对于你当前的小例子,split("\n") 完全足够且更简洁。但如果考虑到代码的可扩展性和健壮性,BufferedReader 是更好的选择。

Scanner 相比 BufferedReader 提供了更丰富的文本解析功能,主要在数据类型解析和分隔符控制方面有优势。

Scanner 的额外控制能力

1. 数据类型自动解析

String data = "John 25 78.5 true\nAlice 30 65.2 false";

try (Scanner scanner = new Scanner(data)) {

while (scanner.hasNext()) {

if (scanner.hasNextInt()) {

int age = scanner.nextInt();

System.out.println("年龄: " + age);

} else if (scanner.hasNextDouble()) {

double weight = scanner.nextDouble();

System.out.println("体重: " + weight);

} else if (scanner.hasNextBoolean()) {

boolean status = scanner.nextBoolean();

System.out.println("状态: " + status);

} else {

String name = scanner.next();

System.out.println("姓名: " + name);

}

}

}

2. 灵活的分隔符控制

String csvData = "A,B,C\n1,2,3\nX,Y,Z";

// 使用逗号作为分隔符

try (Scanner scanner = new Scanner(csvData)) {

scanner.useDelimiter(",|\n"); // 逗号或换行符作为分隔符

while (scanner.hasNext()) {

String token = scanner.next();

System.out.println("Token: " + token);

}

}

3. 模式匹配(正则表达式)

String text = "价格: $25.50, 重量: 1.5kg, 日期: 2023-01-01";

try (Scanner scanner = new Scanner(text)) {

// 查找价格模式

String pricePattern = "\\$\\d+\\.\\d+";

while (scanner.hasNext(pricePattern)) {

String price = scanner.next(pricePattern);

System.out.println("找到价格: " + price);

}

// 重置Scanner查找其他模式

scanner = new Scanner(text);

String datePattern = "\\d{4}-\\d{2}-\\d{2}";

if (scanner.hasNext(datePattern)) {

String date = scanner.next(datePattern);

System.out.println("找到日期: " + date);

}

}

4. 区域设置和数字格式

String europeanData = "1.234,56 2.345,67"; // 欧洲数字格式

try (Scanner scanner = new Scanner(europeanData)) {

scanner.useLocale(Locale.GERMANY); // 使用德国区域设置

while (scanner.hasNextDouble()) {

double number = scanner.nextDouble();

System.out.println("数字: " + number);

}

}

5. 精确的输入验证

String input = "123 456 abc 789";

try (Scanner scanner = new Scanner(input)) {

// 精确控制输入类型

if (scanner.hasNextInt()) {

int first = scanner.nextInt(); // 123

}

if (scanner.hasNextInt()) {

int second = scanner.nextInt(); // 456

}

if (scanner.hasNext("abc")) {

String text = scanner.next(); // abc

}

if (scanner.hasNextInt()) {

int third = scanner.nextInt(); // 789

}

}

与 BufferedReader 的对比

特性 Scanner BufferedReader

数据类型解析 ✅ 自动解析 int, double, boolean 等 ❌ 只能返回 String

分隔符控制 ✅ 高度可配置,支持正则表达式 ❌ 固定按行读取

模式匹配 ✅ 支持正则表达式模式匹配 ❌ 不支持

区域设置 ✅ 支持不同地区的数字格式 ❌ 不支持

性能 ❌ 相对较慢 ✅ 更快

内存使用 ❌ 缓冲区较小 ✅ 缓冲区可配置

简单行读取 ✅ 支持但较慢 ✅ 专门优化

使用场景建议

使用 Scanner 的场景:

// 解析结构化数据

String studentData = "张三 20 计算机 85.5";

try (Scanner scanner = new Scanner(studentData)) {

String name = scanner.next();

int age = scanner.nextInt();

String major = scanner.next();

double score = scanner.nextDouble();

}

// 解析CSV数据

String csv = "1,苹果,5.5\n2,香蕉,3.2";

try (Scanner scanner = new Scanner(csv)) {

scanner.useDelimiter(",|\n");

while (scanner.hasNext()) {

// 按字段解析

}

}

使用 BufferedReader 的场景:

// 简单逐行读取大文件

try (BufferedReader reader = new BufferedReader(new FileReader("largefile.txt"))) {

String line;

while ((line = reader.readLine()) != null) {

// 处理每一行

}

}

// 性能要求高的场景

try (BufferedReader reader = new BufferedReader(new FileReader("file.txt"), 8192)) {

// 使用更大的缓冲区

}

什么时候该用 BufferedReader

只有当文本规模达到以下程度时才需要考虑:

行数:成千上万行

文件大小:几十MB以上

内存敏感:在移动设备或内存受限环境

总结

选择 Scanner 当需要:

自动数据类型转换

复杂的分隔符逻辑

正则表达式模式匹配

解析结构化文本数据

选择 BufferedReader 当需要:

高性能的简单行读取

处理大文件

最小内存占用

简单的文本处理

对于你的原始需求(一行一行读取文本),如果只是简单读取,BufferedReader 性能更好;如果需要解析每行的数据内容,Scanner 更合适。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/23 11:29:46

基于Spring Boot + Vue的租车网站系统

基于Spring Boot Vue的租车网站系统介绍 一、系统背景与目标 传统租车行业依赖线下门店和人工操作&#xff0c;存在信息不透明、流程繁琐、用户体验差等问题。本系统基于Spring Boot&#xff08;后端&#xff09;与Vue.js&#xff08;前端&#xff09;技术栈开发&#xff0c;旨…

作者头像 李华
网站建设 2026/4/23 11:27:31

】setTimeout 延时为 0 的情况

基础问答问题&#xff1a;你在写代码的过程中&#xff0c;在什么时候才会设置 setTimeout 的延时为 0&#xff1f;回答&#xff1a;有如下几种情况避免同步任务阻塞 UI&#xff0c;即在渲染较多数据的时候&#xff0c;可以通过 setTimeout 分批渲染。const data new Array(100…

作者头像 李华
网站建设 2026/4/23 13:11:36

.NET开发中3秒判断该用 IEnumerable 还是 IQueryable

选择 IEnumerable 当&#xff1a;1、数据已在内存中// 数据来自内存集合List<User> users GetUsersFromMemory();var result users.Where(u > u.Age > 18); // 使用 IEnumerable2、需要立即执行查询var users dbContext.Users.ToList() // 立即执行.Where(u >…

作者头像 李华
网站建设 2026/4/23 8:53:23

django基于人脸识别的课堂考勤系统

Django基于人脸识别的课堂考勤系统是一种结合人脸识别技术和Django框架的课堂管理工具&#xff0c;以下是该系统的详细介绍&#xff1a; 一、系统背景与意义 随着教育领域的不断发展和技术的快速进步&#xff0c;传统的课堂考勤方式&#xff08;如手动签到或点名&#xff09;已…

作者头像 李华
网站建设 2026/4/23 11:01:46

侯wenjie经验分享

学弟学妹们好&#xff0c;我是信管2002班的侯wenjie&#xff0c;现阶段是通过拔尖人才计划保研到本校。大家如果对这个计划有兴趣&#xff0c;可以在大三上关注一下官方通知&#xff0c;比较好的地方就是“312”的学年形式&#xff0c;比正常读研少一年。接下来是我的一点小感想…

作者头像 李华
网站建设 2026/4/23 13:12:43

高效制作社团招新海报:稿定设计的工具运用

社团招新是校园组织扩大影响力的关键环节&#xff0c;海报作为视觉传播的核心载体&#xff0c;直接影响招新效率。传统设计流程常因技术门槛&#xff08;如不熟悉专业软件操作&#xff09;或时间限制&#xff08;如临近招新才启动设计&#xff09;导致效果打折——要么内容混乱…

作者头像 李华