【问题标题】:How to read from files with Files.lines(...).forEach(...)?如何使用 Files.lines(...).forEach(...) 读取文件?
【发布时间】:2014-06-10 04:21:24
【问题描述】:

我目前正在尝试从我拥有的纯文本文件中读取行。我在另一个 stackoverflow(Reading a plain text file in Java) 上发现你可以使用 Files.lines(..).forEach(..) 但是我实际上无法弄清楚如何使用 for each 函数来逐行读取文本,有人知道在哪里查找或如何查找吗?

【问题讨论】:

  • 该方法已经在读取文件的每一行,您可以将该行存储在 String 变量中并用它做其他事情...
  • 嗯,您应该阅读有关 Java 8 和 lambdas 的信息;特别是这里,关于Consumer 和单一抽象方法的概念

标签: java file foreach filereader line-by-line


【解决方案1】:

test.txt 的示例内容

Hello
Stack
Over
Flow
com

使用lines()forEach() 方法从该文本文件中读取的代码。

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.Stream;

public class FileLambda {

    public static void main(String args[]) {
        Path path = Paths.of("/root/test.txt");
        try (Stream<String> lines = Files.lines(path)) {
            lines.forEach(s -> System.out.println(s));
        } catch (IOException ex) {
          // do something or re-throw...
        }
    }
    
}

【讨论】:

  • 您可以使用方法参考:System.out::println,仍然会被翻译成相同的字节码。
  • 还有一点:你不应该将Stream 存储为变量,因为它可能会混淆一些读者使用它两次或更多次,这是被禁止的。相反,您可以使用readAllLines 将其保存到List,然后使用此列表中的stream() 方法。
  • 对流使用 try-with-resources 以确保它自动关闭:try (Stream&lt;String&gt; lines = Files.lines(path)) {
  • @DmitryGinzburg 您是否会将Stream 存储为一个变量,以用于对于readAllLines 来说太大的文件?
  • 请不要在生产代码中写这样的空catch块。
【解决方案2】:

避免返回一个列表:

List<String> lines = Files.readAllLines(path); //WARN

请注意,调用Files::readAllLines 时会读取整个文件,生成的字符串数组会立即将文件的所有内容存储在内存中。 因此,如果文件非常大,您可能会遇到OutOfMemoryError 试图将其全部加载到内存中。

改用流:使用返回Stream&lt;String&gt; 对象的Files.lines(Path) 方法,不会遇到同样的问题。 文件的内容是惰性读取和处理的,这意味着在任何给定时间,只有一小部分文件存储在内存中。

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

【讨论】:

【解决方案3】:

使用 Java 8,如果文件存在于 classpath

Files.lines(Paths.get(ClassLoader.getSystemResource("input.txt")
                    .toURI())).forEach(System.out::println);

【讨论】:

    【解决方案4】:

    Files.lines(Path) 需要 Path 参数并返回 Stream&lt;String&gt;Stream#forEach(Consumer) 需要 Consumer 参数。所以调用该方法,传递给它一个Consumer。必须实现该对象才能为每一行执行您想要的操作。

    这是 Java 8,因此您可以使用 lambda 表达式或方法引用来提供 Consumer 参数。

    【讨论】:

      【解决方案5】:

      我已经创建了一个示例,你可以使用 Stream 来过滤/

      public class ReadFileLines {
          public static void main(String[] args) throws IOException {
              Stream<String> lines = Files.lines(Paths.get("C:/SelfStudy/Input.txt"));
      //      System.out.println(lines.filter(str -> str.contains("SELECT")).count());
      
      //Stream gets closed once you have run the count method.
              System.out.println(lines.parallel().filter(str -> str.contains("Delete")).count());
          }
      }
      

      示例 input.txt。

      SELECT Every thing
      Delete Every thing
      Delete Every thing
      Delete Every thing
      Delete Every thing
      Delete Every thing
      Delete Every thing
      

      【讨论】:

        猜你喜欢
        • 2019-04-25
        • 1970-01-01
        • 2015-04-14
        • 1970-01-01
        • 2019-07-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-01-06
        相关资源
        最近更新 更多