Java实现一行一行读取文本的多种方法详解
作者:VipSoft
这篇文章主要为大家详细介绍了Java实现一行一行读取文本的多种方法,文中的示例代码讲解详细,具有一定的借鉴价值,有需要的小伙伴可以了解下
在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
更合适。
以上就是Java实现一行一行读取文本的多种方法详解的详细内容,更多关于Java按行读取文本的资料请关注脚本之家其它相关文章!