如何使用 Files.lines(...).forEach(...) 读取文件?
Posted
技术标签:
【中文标题】如何使用 Files.lines(...).forEach(...) 读取文件?【英文标题】:How to read from files with Files.lines(...).forEach(...)? 【发布时间】:2014-06-10 04:21:24 【问题描述】:我目前正在尝试从我拥有的纯文本文件中读取行。我在另一个 ***(Reading a plain text file in Java) 上发现你可以使用 Files.lines(..).forEach(..) 但是我实际上无法弄清楚如何使用 for each 函数来逐行读取文本,有人知道在哪里查找或如何查找吗?
【问题讨论】:
该方法已经在读取文件的每一行,您可以将该行存储在String
变量中并用它做其他事情...
嗯,您应该阅读有关 Java 8 和 lambdas 的信息;特别是这里,关于Consumer
和单一抽象方法的概念
【参考方案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<String> lines = Files.lines(path))
@DmitryGinzburg 您是否会将Stream
存储为一个变量,以用于对于readAllLines
来说太大的文件?
请不要在生产代码中写这样的空catch块。【参考方案2】:
避免返回一个列表:
List<String> lines = Files.readAllLines(path); //WARN
请注意,调用Files::readAllLines
时会读取整个文件,生成的字符串数组会立即将文件的所有内容存储在内存中。
因此,如果文件非常大,您可能会遇到OutOfMemoryError
试图将其全部加载到内存中。
改用流:使用返回Stream<String>
对象的Files.lines(Path)
方法,不会遇到同样的问题。
文件的内容是惰性读取和处理的,这意味着在任何给定时间,只有一小部分文件存储在内存中。
Files.lines(path).forEach(System.out::println);
【讨论】:
我有一个疑问。 Files.lines() 会返回每一行的流还是会从整个文件中返回一个流?请澄清。 "将文件中的所有行作为流读取。" docs.oracle.com/javase/8/docs/api/java/nio/file/…【参考方案3】:使用 Java 8,如果文件存在于 classpath
:
Files.lines(Paths.get(ClassLoader.getSystemResource("input.txt")
.toURI())).forEach(System.out::println);
【讨论】:
【参考方案4】:Files.lines(Path)
需要 Path
参数并返回 Stream<String>
。 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
【讨论】:
以上是关于如何使用 Files.lines(...).forEach(...) 读取文件?的主要内容,如果未能解决你的问题,请参考以下文章
这是 Files.lines() 中的错误,还是我对并行流有误解?