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

如何用Java Stream API有效解析文本文件

郜昊苍
2023-03-14

我理解了如何用Java8流从文件中获取特定的数据。例如,如果我们需要从像这样的文件中获取加载的包

2015-01-06 11:33:03 b.s.d.task [INFO] Emitting: eVentToRequestsBolt __ack_ack 
2015-01-06 11:33:03 c.s.p.d.PackagesProvider [INFO] ===---> Loaded package com.foo.bar
2015-01-06 11:33:04 b.s.d.executor [INFO] Processing received message source: eventToManageBolt:2, stream: __ack_ack, id: {}, [-6722594615019711369 -1335723027906100557]
2015-01-06 11:33:04 c.s.p.d.PackagesProvider [INFO] ===---> Loaded package co.il.boo
2015-01-06 11:33:04 c.s.p.d.PackagesProvider [INFO] ===---> Loaded package dot.org.biz
List<String> packageList = Files.lines(Paths.get(args[1])).filter(line -> line.contains("===---> Loaded package"))
        .map(line -> line.split(" "))
        .map(arr -> arr[arr.length - 1]).collect(Collectors.toList());

我从解析文件示例中获取(并稍加修改)代码。

但是,如果我们还需要从同一个日志文件中获取发射:事件的所有日期(和时间)呢?我们如何在使用相同的流的过程中做到这一点呢?

我只能想象使用collect(groupingBy(...)),它在解析之前将带有加载包的行和带有emitting:的行分组,然后分别解析每个组(一个映射条目)。但这将创建一个包含日志文件中所有原始数据的映射,这非常消耗内存。

是否有类似的方法可以有效地从Java8流中提取多种类型的数据?

共有1个答案

秦俊发
2023-03-14

您可以在不定义新的收集器和使用更命令式的第三方库的情况下解决它。首先,您需要定义一个表示解析结果的类。它应该有两种方法来接受输入行并与现有的部分结果相结合:

class Data {
    List<String> packageDates = new ArrayList<>();
    List<String> emittingDates = new ArrayList<>();

    // Consume single input line
    void accept(String line) {
        if(line.contains("===---> Loaded package"))
            packageDates.add(line.substring(0, "XXXX-XX-XX".length()));
        if(line.contains("Emitting"))
            packageDates.add(line.substring(0, "XXXX-XX-XX XX:XX:XX".length()));
    }

    // Combine two partial results
    void combine(Data other) {
        packageDates.addAll(other.packageDates);
        emittingDates.addAll(other.emittingDates);
    }
}

现在你可以用一种非常简单的方式收集:

Data result = Files.lines(Paths.get(args[1]))
    .collect(Data::new, Data::accept, Data::combine);
 类似资料:
  • 问题内容: 我试图找到一种解析文件的方法,该文件包含固定宽度的线。例如,前20个字符代表一列,从21:30开始代表另一列,依此类推。 假设该行包含100个字符,将行解析为多个组件的有效方法是什么? 我可以每行使用字符串切片,但是如果行很大,这会有点难看。还有其他快速方法吗? 问题答案: 由于Python标准库的模块是用C编写的,因此使用它非常容易而且非常快捷。 这是可以用来完成您想要的事情的方法。

  • 问题内容: 我正在寻找一种将复杂文本文件解析为pandas DataFrame的简单方法。下面是一个示例文件,我希望解析后的结果是什么样,以及我当前的方法。 有什么方法可以使其更简洁/更快/更pythonic /更易读? 我也把这个问题放在了Code Review上 。 我最终写了一篇博客文章向初学者解释。 这是一个示例文件: 这是我希望解析后的结果看起来像什么: 这是我目前解析的方式: 问题答案

  • 我有这个文件要处理,我正试图找出如何将第二行作为不同的对象来读取。在这一行的末尾,最后一项是公交车的数量。第二行、第四行等应包含idBus和noOfBus,并用逗号分隔。 基于这些课程 我想要一个函数来处理CSV文件中所有公交车和大学线路的列表。它必须使用流API。我不知道这是否可能或如何进行。 当然,可以根据类进行更改,但保留变量,不添加任何额外内容。 我认为最方便的方法是浏览文件,根据两个班级

  • 问题内容: 我是iOS开发人员中的新手,并且尝试解析本地Json文件,例如 这是我的代码: 我在此站点上找到了一个示例,但出现以下错误 -JSONValue失败。错误是:对象键后不期望令牌“值分隔符”。 问题答案: JSON具有严格的键/值表示法,用于R4和响应的键/值对不正确。试试这个: 如果您从文件中读取字符串,则不需要所有的斜杠。 文件将如下所示: {“ quizz”:[{“ id”:“ 1

  • 我无法理解为什么当我通过的文本符合格式时,我会得到DateTimeParseException错误。下面是导致该问题的代码: 奇怪的是。每当我查询用户一段时间(让我们以00:02:30为例),它就会完全按照我想要的方式运行。但是当我使用我的方法(从文本文件中提取时间)时,它会出现错误: 线程“main”java.time.format.DateTimeParseException中出现异常:无法分

  • 我有一个非常简单的产品评论JSON,比如: 我想用GSON把它读到我的Java应用程序中。我构建了一个类来保存每次复习的结果: 使用这段代码,我只能检索JSON中的第一个评论,所以我的问题是:如何遍历所有阅读器并获得下一个评论?我不需要将评论存储在列表中,只需要访问对象一次。任何帮助都大于欢迎。