java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java按行读取文本

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);

推荐方案

最简洁的方式是使用 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();
}

优点:

缺点:

推荐选择

场景 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 的对比

特性ScannerBufferedReader
数据类型解析✅ 自动解析 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

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

总结

选择 Scanner 当需要:

选择 BufferedReader 当需要:

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

以上就是Java实现一行一行读取文本的多种方法详解的详细内容,更多关于Java按行读取文本的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文