找回密码
 立即注册
首页 业界区 业界 Java 一行一行的读取文本,小Demo 大学问

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

莅耸 2025-9-30 14:09:34
  1. String str="A\n" +
  2.             "B\n" +
  3.             "C";
复制代码
在Java中,有多种方式可以一行一行地读取文本。以下是几种常用的方法:
1. 使用 BufferedReader + FileReader
  1. String str = "A\n" + "B\n" + "C";
  2. // 方法1:从字符串读取
  3. try (BufferedReader reader = new BufferedReader(new StringReader(str))) {
  4.     String line;
  5.     while ((line = reader.readLine()) != null) {
  6.         System.out.println(line);
  7.     }
  8. } catch (IOException e) {
  9.     e.printStackTrace();
  10. }
  11. // 方法2:从文件读取
  12. try (BufferedReader reader = new BufferedReader(new FileReader("filename.txt"))) {
  13.     String line;
  14.     while ((line = reader.readLine()) != null) {
  15.         System.out.println(line);
  16.     }
  17. } catch (IOException e) {
  18.     e.printStackTrace();
  19. }
复制代码
2. 使用 Scanner
  1. String str = "A\n" + "B\n" + "C";
  2. // 从字符串读取
  3. try (Scanner scanner = new Scanner(str)) {
  4.     while (scanner.hasNextLine()) {
  5.         String line = scanner.nextLine();
  6.         System.out.println(line);
  7.     }
  8. }
  9. // 从文件读取
  10. try (Scanner scanner = new Scanner(new File("filename.txt"))) {
  11.     while (scanner.hasNextLine()) {
  12.         String line = scanner.nextLine();
  13.         System.out.println(line);
  14.     }
  15. } catch (FileNotFoundException e) {
  16.     e.printStackTrace();
  17. }
复制代码
3. 使用 Files.lines() (Java 8+)
  1. String str = "A\n" + "B\n" + "C";
  2. // 从字符串读取(需要先写入临时文件)
  3. try {
  4.     Path tempFile = Files.createTempFile("temp", ".txt");
  5.     Files.write(tempFile, str.getBytes());
  6.    
  7.     Files.lines(tempFile).forEach(System.out::println);
  8.    
  9.     // 清理临时文件
  10.     Files.deleteIfExists(tempFile);
  11. } catch (IOException e) {
  12.     e.printStackTrace();
  13. }
  14. // 从文件读取
  15. try {
  16.     Files.lines(Paths.get("filename.txt")).forEach(System.out::println);
  17. } catch (IOException e) {
  18.     e.printStackTrace();
  19. }
复制代码
4. 使用 String 的 split() 方法(适用于字符串)
  1. String str = "A\n" + "B\n" + "C";
  2. String[] lines = str.split("\n");
  3. for (String line : lines) {
  4.     System.out.println(line);
  5. }
  6. //处理空行
  7. String[] lines = str.split("\\r?\\n|\\r");
  8. List<String> nonEmptyLines = Arrays.stream(lines)
  9.                                   .filter(line -> !line.trim().isEmpty())
  10.                                   .collect(Collectors.toList());
复制代码
5. 使用 Lines() 方法 (Java 11+)
  1. String str = "A\n" + "B\n" + "C";
  2. // 从字符串读取
  3. str.lines().forEach(System.out::println);
复制代码
推荐方案


  • 对于字符串:使用 str.lines() (Java 11+) 或 split("\n")
  • 对于文件:使用 Files.lines() (Java 8+) 或 BufferedReader
  • 需要更多控制:使用 Scanner
最简洁的方式是使用 Java 11 的 lines() 方法:
  1. String str = "A\n" + "B\n" + "C";
  2. str.lines().forEach(System.out::println);
复制代码
输出结果:
  1. A
  2. B
  3. C
复制代码
在 Java 8 环境下,split("\n") 和 BufferedReader 各有优缺点,具体选择取决于使用场景:
性能对比

1. split("\n") - 适用于小文本
  1. String str = "A\n" + "B\n" + "C";
  2. String[] lines = str.split("\n");
  3. for (String line : lines) {
  4.     System.out.println(line);
  5. }
复制代码
优点:

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

  • 一次性加载所有内容到内存,大文本会占用大量内存
  • 需要处理尾部的空行问题
2. BufferedReader - 适用于大文本或文件
  1. String str = "A\n" + "B\n" + "C";
  2. try (BufferedReader reader = new BufferedReader(new StringReader(str))) {
  3.     String line;
  4.     while ((line = reader.readLine()) != null) {
  5.         System.out.println(line);
  6.     }
  7. } catch (IOException e) {
  8.     e.printStackTrace();
  9. }
复制代码
优点:

  • 内存效率高,逐行读取,适合大文件
  • 自动处理不同操作系统的换行符(\n, \r\n, \r)
  • 统一的接口处理字符串和文件
缺点:

  • 代码相对冗长
  • 需要处理异常
推荐选择

场景 1:小文本,内容已知且不大
  1. // 使用 split("\n")
  2. String[] lines = str.split("\n");
  3. Arrays.stream(lines).forEach(System.out::println);
复制代码
场景 2:大文本或需要处理文件
  1. // 使用 BufferedReader
  2. try (BufferedReader reader = new BufferedReader(new StringReader(str))) {
  3.     reader.lines().forEach(System.out::println); // Java 8 Stream API
  4. } catch (IOException e) {
  5.     e.printStackTrace();
  6. }
复制代码
场景 3:Java 8 更优雅的写法
  1. // 结合 BufferedReader 和 Stream API
  2. try (BufferedReader reader = new BufferedReader(new StringReader(str))) {
  3.     List<String> lines = reader.lines().collect(Collectors.toList());
  4.     lines.forEach(System.out::println);
  5. } catch (IOException e) {
  6.     e.printStackTrace();
  7. }
复制代码
实际建议

对于你的具体案例:
  1. String str = "A\n" + "B\n" + "C";
  2. // 如果确定文本很小,用 split 更简洁
  3. String[] lines = str.split("\n");
  4. for (String line : lines) {
  5.     System.out.println(line);
  6. }
  7. // 如果要养成好习惯或处理可能的大文本,用 BufferedReader
  8. try (BufferedReader reader = new BufferedReader(new StringReader(str))) {
  9.     reader.lines().forEach(System.out::println);
  10. } catch (IOException e) {
  11.     e.printStackTrace();
  12. }
复制代码
总结: 对于你当前的小例子,split("\n") 完全足够且更简洁。但如果考虑到代码的可扩展性和健壮性,BufferedReader 是更好的选择。
Scanner 相比 BufferedReader 提供了更丰富的文本解析功能,主要在数据类型解析和分隔符控制方面有优势。
Scanner 的额外控制能力

1. 数据类型自动解析
  1. String data = "John 25 78.5 true\nAlice 30 65.2 false";
  2. try (Scanner scanner = new Scanner(data)) {
  3.     while (scanner.hasNext()) {
  4.         if (scanner.hasNextInt()) {
  5.             int age = scanner.nextInt();
  6.             System.out.println("年龄: " + age);
  7.         } else if (scanner.hasNextDouble()) {
  8.             double weight = scanner.nextDouble();
  9.             System.out.println("体重: " + weight);
  10.         } else if (scanner.hasNextBoolean()) {
  11.             boolean status = scanner.nextBoolean();
  12.             System.out.println("状态: " + status);
  13.         } else {
  14.             String name = scanner.next();
  15.             System.out.println("姓名: " + name);
  16.         }
  17.     }
  18. }
复制代码
2. 灵活的分隔符控制
  1. String csvData = "A,B,C\n1,2,3\nX,Y,Z";
  2. // 使用逗号作为分隔符
  3. try (Scanner scanner = new Scanner(csvData)) {
  4.     scanner.useDelimiter(",|\n"); // 逗号或换行符作为分隔符
  5.    
  6.     while (scanner.hasNext()) {
  7.         String token = scanner.next();
  8.         System.out.println("Token: " + token);
  9.     }
  10. }
复制代码
3. 模式匹配(正则表达式)
  1. String text = "价格: $25.50, 重量: 1.5kg, 日期: 2023-01-01";
  2. try (Scanner scanner = new Scanner(text)) {
  3.     // 查找价格模式
  4.     String pricePattern = "\\$\\d+\\.\\d+";
  5.     while (scanner.hasNext(pricePattern)) {
  6.         String price = scanner.next(pricePattern);
  7.         System.out.println("找到价格: " + price);
  8.     }
  9.    
  10.     // 重置Scanner查找其他模式
  11.     scanner = new Scanner(text);
  12.     String datePattern = "\\d{4}-\\d{2}-\\d{2}";
  13.     if (scanner.hasNext(datePattern)) {
  14.         String date = scanner.next(datePattern);
  15.         System.out.println("找到日期: " + date);
  16.     }
  17. }
复制代码
4. 区域设置和数字格式
  1. String europeanData = "1.234,56 2.345,67"; // 欧洲数字格式
  2. try (Scanner scanner = new Scanner(europeanData)) {
  3.     scanner.useLocale(Locale.GERMANY); // 使用德国区域设置
  4.    
  5.     while (scanner.hasNextDouble()) {
  6.         double number = scanner.nextDouble();
  7.         System.out.println("数字: " + number);
  8.     }
  9. }
复制代码
5. 精确的输入验证
  1. String input = "123 456 abc 789";
  2. try (Scanner scanner = new Scanner(input)) {
  3.     // 精确控制输入类型
  4.     if (scanner.hasNextInt()) {
  5.         int first = scanner.nextInt(); // 123
  6.     }
  7.     if (scanner.hasNextInt()) {
  8.         int second = scanner.nextInt(); // 456
  9.     }
  10.     if (scanner.hasNext("abc")) {
  11.         String text = scanner.next(); // abc
  12.     }
  13.     if (scanner.hasNextInt()) {
  14.         int third = scanner.nextInt(); // 789
  15.     }
  16. }
复制代码
与 BufferedReader 的对比

特性ScannerBufferedReader数据类型解析✅ 自动解析 int, double, boolean 等❌ 只能返回 String分隔符控制✅ 高度可配置,支持正则表达式❌ 固定按行读取模式匹配✅ 支持正则表达式模式匹配❌ 不支持区域设置✅ 支持不同地区的数字格式❌ 不支持性能❌ 相对较慢✅ 更快内存使用❌ 缓冲区较小✅ 缓冲区可配置简单行读取✅ 支持但较慢✅ 专门优化使用场景建议

使用 Scanner 的场景:
  1. // 解析结构化数据
  2. String studentData = "张三 20 计算机 85.5";
  3. try (Scanner scanner = new Scanner(studentData)) {
  4.     String name = scanner.next();
  5.     int age = scanner.nextInt();
  6.     String major = scanner.next();
  7.     double score = scanner.nextDouble();
  8. }
  9. // 解析CSV数据
  10. String csv = "1,苹果,5.5\n2,香蕉,3.2";
  11. try (Scanner scanner = new Scanner(csv)) {
  12.     scanner.useDelimiter(",|\n");
  13.     while (scanner.hasNext()) {
  14.         // 按字段解析
  15.     }
  16. }
复制代码
使用 BufferedReader 的场景:
  1. // 简单逐行读取大文件
  2. try (BufferedReader reader = new BufferedReader(new FileReader("largefile.txt"))) {
  3.     String line;
  4.     while ((line = reader.readLine()) != null) {
  5.         // 处理每一行
  6.     }
  7. }
  8. // 性能要求高的场景
  9. try (BufferedReader reader = new BufferedReader(new FileReader("file.txt"), 8192)) {
  10.     // 使用更大的缓冲区
  11. }
复制代码
什么时候该用 BufferedReader

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

  • 行数:成千上万行
  • 文件大小:几十MB以上
  • 内存敏感:在移动设备或内存受限环境
总结

选择 Scanner 当需要:

  • 自动数据类型转换
  • 复杂的分隔符逻辑
  • 正则表达式模式匹配
  • 解析结构化文本数据
选择 BufferedReader 当需要:

  • 高性能的简单行读取
  • 处理大文件
  • 最小内存占用
  • 简单的文本处理
对于你的原始需求(一行一行读取文本),如果只是简单读取,BufferedReader 性能更好;如果需要解析每行的数据内容,Scanner 更合适。
RandomAccessFile、FileInputStream、MappedByteBuffer、FileChannel 区别、应用场景及示例

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册