【问题标题】:Search for a String in a Text File using Java 8使用 Java 8 在文本文件中搜索字符串
【发布时间】:2015-09-24 02:53:55
【问题描述】:

我有一个长文本文件,我想从中读取并提取一些数据。使用 JavaFX 和 FXML,我使用 FileChooser 加载文件以获取文件路径。 我的 controller.java 有以下内容:

private void handleButtonAction(ActionEvent event) throws IOException {
        FileChooser fileChooser = new FileChooser();
        FileChooser.ExtensionFilter extFilter = new FileChooser.ExtensionFilter("TXT files (*.txt)", "*.txt");
        fileChooser.getExtensionFilters().add(extFilter);
        File file = fileChooser.showOpenDialog(stage);
        System.out.println(file);
         stage = (Stage) button.getScene().getWindow();


    }

文本文件示例:请注意,部分文件内容分为两行。例如 -Ba\ 10.10.10.3 是第一行的一部分。

net ip-interface create 10.10.10.2 255.255.255.128 MGT-1 -Ba \
10.10.10.3
net ip-interface create 192.168.1.1 255.255.255.0 G-1 -Ba \
192.168.1.2 
net route table create 10.10.10.5 255.255.255.255 10.10.10.1 -i \
MGT-1
net route table create 10.10.10.6  255.255.255.255 10.10.10.1 -i \
MGT-1

我正在寻找一种方法来搜索这个(文件)并输出以下内容:

MGT-1 ip-interface 10.10.10.2 
MGT-1 Backup ip-interface 10.10.10.3
G-1 ip-interface 192.168.1.1
G-1 Backup Ip-interface 192.168.1.2
MGT-1 route 10.10.10.5 DFG 10.10.10.1
MGT-1 route 10.10.10.6 DFG 10.10.10.1

【问题讨论】:

  • 你能用awk吗? jawk.sourceforge.net 你的结果中 DFG 来自哪里?
  • 感谢您的评论!我是Java新手,所以我正在寻找指针。如果我需要使用 AWK,那就这样吧。 DFG 代表默认网关。网络路由表(通过默认网关 10.10.10.1 为 10.10.10.5-6 创建静态路由)
  • 如果内存不是一个约束,你可以:List<String> lines = Files.readAllLines(file.toPath(), StandardCharsets.UTF_8); 得到一个包含所有行的列表。然后,您可以遍历这些行并根据需要解析它们。
  • 关于如何以某种方式解析它们以获得上述输出的任何建议。例如,对于模式“MGT-1 -Ba \”,我如何输出下一行? 10.10.10.3 我该怎么做?或者我怎样才能在“ip-interface create”之后输入IP地址。 10.10.10.2?我正在寻找有关如何执行解析以获取上述输出数据的想法。我听说 Java 8 使用流,这是我可以在这里使用的东西吗?
  • “Backup”(不在输入中)和“Ip-interface”(大小写变化)从何而来?

标签: java file javafx java-8 javafx-8


【解决方案1】:

当然,您可以使用BufferedReader.linesFiles.lines 将输入文件作为行流读取。然而这里棘手的事情是如何处理尾随的"\"。有几种可能的解决方案。您可以编写自己的 Reader 包装现有的 Reader 并忽略 EOL 后面的斜线。或者,您可以编写自定义IteratorSpliterator,它将BufferedReader.lines 流作为输入并处理这种情况。我建议使用我的 StreamEx 库,该库已经有一个用于此类任务的方法,称为 collapse

StreamEx.ofLines(reader).collapse((a, b) -> a.endsWith("\\"), 
                                  (a, b) -> a.substring(0, a.length()-1).concat(b));

第一个参数是应用于两个相邻行的谓词,如果应该合并行,则应该返回 true。第二个参数是实际合并两行的函数(我们通过substring 砍掉斜线,然后连接下一行)。

现在您可以只用空格分割行,然后根据您的任务将其转换为一到两行输出。最好通过单独的方法来做到这一点。整个代码:

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.regex.Pattern;
import java.util.stream.Stream;

import javax.util.streamex.StreamEx;

public class ParseFile {
    static Stream<String> convertLine(String[] fields) {
        switch(fields[1]) {
        case "ip-interface":
            return Stream.of(fields[5]+" "+fields[1]+" "+fields[3],
                             fields[5]+" Backup "+fields[1]+" "+fields[7]);
        case "route":
            return Stream.of(fields[8]+" route "+fields[4]+" DFG "+fields[6]);
        default:
            throw new IllegalArgumentException("Unrecognized input: "+
                                               String.join(" ", fields));
        }
    }

    static Stream<String> convert(Reader reader) {
        return StreamEx.ofLines(reader)
                .collapse((a, b) -> a.endsWith("\\"), 
                          (a, b) -> a.substring(0, a.length()-1).concat(b))
                .map(Pattern.compile("\\s+")::split)
                .flatMap(ParseFile::convertLine);
    }

    public static void main(String[] args) throws IOException {
        try(Reader r = new InputStreamReader(
            ParseFile.class.getResourceAsStream("test.txt"))) {
            convert(r).forEach(System.out::println);
        }
    }
}

【讨论】:

  • 谢谢,看起来它可以解决问题,正在处理它......但是有两件事 1) 我怎样才能将我的文件路径传递给你的 ParseFile.java。并从我的controller.java(上面提到)返回输出? 2)如何在不使用您的包(用于我的学习过程)的情况下合并 2 行并打印我需要的内容。我似乎在任何地方都找不到此信息。
  • 我从 ParseFile 中删除了你的 main 并添加了 try(Reader r = new InputStreamReader( ParseFile.class.getResourceAsStream("file"))) { convert(r).forEach(System.out::打印); } 在我的控制器中,但它不工作
猜你喜欢
  • 2015-11-02
  • 2021-05-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多