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

String str="An" +             "Bn" +             "C"; 

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

1. 使用 BufferedReader + FileReader

String str = "An" + "Bn" + "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 = "An" + "Bn" + "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 = "An" + "Bn" + "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 = "An" + "Bn" + "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 = "An" + "Bn" + "C";  // 从字符串读取 str.lines().forEach(System.out::println); 

推荐方案

  • 对于字符串:使用 str.lines() (Java 11+) 或 split("n")
  • 对于文件:使用 Files.lines() (Java 8+) 或 BufferedReader
  • 需要更多控制:使用 Scanner

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

String str = "An" + "Bn" + "C"; str.lines().forEach(System.out::println); 

输出结果:

A B C 

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

性能对比

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

String str = "An" + "Bn" + "C"; String[] lines = str.split("n"); for (String line : lines) {     System.out.println(line); } 

优点:

  • 代码简洁,一行搞定
  • 适合已知内容较小的字符串
  • 可以直接得到数组,方便后续处理

缺点:

  • 一次性加载所有内容到内存,大文本会占用大量内存
  • 需要处理尾部的空行问题

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

String str = "An" + "Bn" + "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, rn, 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 = "An" + "Bn" + "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 truenAlice 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,Cn1,2,3nX,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.5n2,香蕉,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 更合适。

RandomAccessFile、FileInputStream、MappedByteBuffer、FileChannel 区别、应用场景及示例

发表评论

评论已关闭。

相关文章

当前内容话题