当前位置: 首页 > 知识库问答 >
问题:

使用lines()流Lambda,但需要关闭

印晋
2023-03-14

我想在我的应用程序中做的是,让用户使用filechooser选择一系列文本文件,然后我的应用程序将过滤其中一些不包含指定子字符串的文件

这是我使用lambda的代码:

    FileChooser fileChooser = new FileChooser();
    fileChooser.setTitle("choose files");
    fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("TXT files (*.txt)", "*.txt"));
    fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("CSV files (*.csv)", "*.csv"));
    List<File> targetList = fileChooser.showOpenMultipleDialog(primaryStage);
    if (targetList == null) {
        System.out.println("targetList none");
    }
    targetList.parallelStream()
            .filter(f->{
                        try {
                            return new BufferedReader(new FileReader(f)).lines()
                                    .anyMatch(line-> (line.indexOf(",")!=-1));
                        } catch (FileNotFoundException e) {
                            e.printStackTrace();
                        }
                        return false;
                    }
            )
            .collect(Collectors.toList());

它工作,但不完美!因为BufferedReader永远不会关闭,我需要用Buiky catesment包装它。

任何人都可以优雅地提出改进建议?

共有3个答案

郎曜文
2023-03-14

使用try with资源:

targetList.parallelStream()
        .filter(f -> {
                    try (BufferedReader br = new BufferedReader(new FileReader(f))) {
                        return br.lines().anyMatch(line -> (line.contains(",")));
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    return false;
                }
        )
        .collect(Collectors.toList());
伊俊能
2023-03-14

您可以使用try with resources语句:

try-with-资源语句确保在语句末尾关闭每个资源。

targetList.parallelStream()
        .filter(f -> {
            try (BufferedReader br = new BufferedReader(new FileReader(f))) {
                return br.lines().anyMatch(line -> (line.indexOf(",") != -1));
            } catch (IOException e) {
                e.printStackTrace();
            }
            return false;
        })
        .collect(Collectors.toList());
翟泰
2023-03-14

这可以用与本答案相同的技巧以优雅的方式解决。

可以创建一个应用函数的实用函数,然后使用try-with-resource-语句可靠地关闭资源。

使用该选项,您的代码将如下所示:

List<File> filteredList = targetList.parallelStream()
    .filter(f -> f.exists())
    .filter(f -> applyAndClose(
        () -> new BufferedReader(new FileReader(f)),
        reader -> reader.lines().anyMatch(line-> (line.indexOf(",") !=-1))))
    .collect(Collectors.toList());

请注意,您必须保存collect方法的结果,否则将丢失!此外,我在另一个步骤中测试文件是否存在。

效用函数本身如下所示:

/**
 * Applies a function to a resource and closes it afterwards.
 * @param sup Supplier of the resource that should be closed
 * @param op operation that should be performed on the resource before it is closed
 * @return The result of calling op.apply on the resource 
 */
public static <A extends AutoCloseable, B> B applyAndClose(Callable<A> sup, Function<A, B> op) {
    try (A res = sup.call()) {
        return op.apply(res);
    } catch (RuntimeException exc) {
        throw exc;
    } catch (Exception exc) {
        throw new RuntimeException("Wrapped in applyAndClose", exc);
    }
}
  • java。io。类和相关API大多已过时。自Java 7以来,处理文件的标准方法是Java。nio。文件路径和文件类

使用这些您的代码将如下所示:

List<Path> filteredList = targetList.stream()
    .filter(f -> Files.exists(f))
    .filter(f -> applyAndClose(
        () -> Files.lines(f),
        lines -> lines.anyMatch(line-> line.contains(","))))
    .collect(toList());
 类似资料:
  • 问题内容: 我认为这个问题已经存在,但是我找不到。 我不明白,为什么必须要有一个功能接口才能使用lambda。考虑以下示例: 这可以正常工作,但是如果您取消注释行,则不会。为什么?以我的理解,编译器应该能够区分这两种方法,因为它们具有不同的输入参数。为什么我需要一个功能接口并炸毁我的代码? 编辑:链接的重复项没有回答我的问题,因为我在询问不同的方法参数。但是在这里,我得到了一些非常有用的答案,这要

  • 此函数返回值1或输入流中要读取的行数。 文件名作为函数的输入。 语法 (Syntax) lines(filename) 参数 (Parameters) filename - 这是文件的名称。 返回值 (Return Value) 此函数返回值1或输入流中要读取的行数。 例子 (Example) /* Main program */ do while lines(Example.txt) >

  • 问题内容: Commons-IO有一种方法,可以从输入流中读取所有内容: 我的问题是使用后是否应手动关闭输入流? 我以为IOUtils可能会关闭它,因为它已读取所有内容,但是我在源代码中找不到它。 问题答案: Javadoc说: 只要有可能,此类中的方法就不会刷新或关闭流。这是为了避免对流的来源和进一步使用做出不可移植的假设。因此,调用方仍然负责在使用后关闭流。

  • 对于接受文件输入的APIendpoint,我们需要手动关闭还是框架为我们这样做? 我查了新泽西的文件,但找不到任何关于它的信息。 寻找可靠的来源或某种方式来验证它。

  • 有时,在处理流的两个步骤之间对流中的每个元素进行“处理”(例如打印)会很方便,例如调试。 一个简单的例子可能是这样的,不幸的是,这不起作用,因为消耗流: 如何做到这一点?

  • 问题内容: 我有一个网站,它的点击率很高,我遇到了问题,JDCB连接错误。 我对关闭有点困惑,我需要关闭还是仅关闭就足够了。 另外,我需要关闭它吗? 问题答案: 是的,您必须关闭PreparedStatement和结果集,因为它们可能导致内存泄漏。有关更多信息,请访问 http://docs.oracle.com/javase/tutorial/jdbc/basics/prepared.html