使用Java 8在文本文件中搜索字符串

使用Java 8在文本文件中搜索字符串,java,file,javafx,java-8,javafx-8,Java,File,Javafx,Java 8,Javafx 8,我有一个很长的文本文件,我想从中读取和提取一些数据。使用JavaFX和FXML,我使用FileChooser加载文件以获得文件路径。 My controller.java具有以下功能: private void handleButtonAction(ActionEvent event) throws IOException { FileChooser fileChooser = new FileChooser(); FileChooser.ExtensionFil

我有一个很长的文本文件,我想从中读取和提取一些数据。使用JavaFX和FXML,我使用FileChooser加载文件以获得文件路径。 My 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

当然,您可以使用
BufferedReader.lines
Files.lines
将输入文件作为行流读取。然而,这里的棘手问题是如何处理尾随的
“\”
。有几种可能的解决办法。您可以编写自己的
读卡器
,它包装现有的
读卡器
,只需忽略斜杠后跟EOL。或者,您可以编写一个自定义的
迭代器
拆分器
,它将
BufferedReader.lines
流作为输入并处理这种情况。我建议使用我的库,它已经有了一个用于此类任务的方法,名为:

第一个参数是应用于两个相邻行的谓词,如果要合并行,则应返回true。第二个参数是实际合并两行的函数(我们通过
子字符串
切掉斜杠,然后连接下一行)

现在,您只需按空格分割该行,然后根据任务将其转换为一行或两行输出。最好用单独的方法。整个代码:

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);
        }
    }
}
import java.io.IOException;
导入java.io.InputStreamReader;
导入java.io.Reader;
导入java.util.regex.Pattern;
导入java.util.stream.stream;
导入javax.util.streamex.streamex;
公共类解析文件{
静态流转换行(字符串[]字段){
开关(字段[1]){
案例“ip接口”:
返回流.of(字段[5]+“”+字段[1]+“”+字段[3],
字段[5]+“备份”+字段[1]+“”+字段[7]);
案例“路线”:
返回流。of(字段[8]+“路由”+字段[4]+“DFG”+字段[6]);
违约:
抛出新的IllegalArgumentException(“无法识别的输入:”+
join(“,fields));
}
}
静态流转换(读卡器){
返回流x.of Lines(读卡器)
.collapse((a,b)->a.endsWith(\\),
(a,b)->a.substring(0,a.length()-1.concat(b))
.map(Pattern.compile(“\\s+”)::split)
.flatMap(ParseFile::convertLine);
}
公共静态void main(字符串[]args)引发IOException{
try(读卡器r=新的InputStreamReader(
ParseFile.class.getResourceAsStream(“test.txt”)){
convert(r).forEach(System.out::println);
}
}
}

您能使用awk吗?那么DFG从何而来呢?谢谢你的评论!我是Java新手,所以我正在寻找指针。如果我需要使用AWK,就这样吧。DFG代表默认网关。Net路由表(通过默认网关10.10.10.1为10.10.10.5-6创建静态路由)如果内存不是约束,您可以:
List lines=Files.readAllLines(file.toPath(),StandardCharsets.UTF_8)
以获取包含所有行的列表。然后,您可以在这些行上循环并根据需要解析它们。关于如何解析它们以获得上述输出的任何建议。例如,对于模式“MGT-1-Ba\”如何输出下一行?10.10.10.3我该怎么做?或者如何在“创建IP接口”之后输出IP地址。10.10.10.2? 我正在寻找有关如何执行解析以获得上述输出数据的想法。我听说Java 8使用流,这是我可以在这里使用的东西吗?从哪里来的“备份”(不在输入中)和“Ip接口”(案例更改)?谢谢,看起来它会成功的,正在努力。。。。但是有两件事1)如何将文件路径传递给ParseFile.java。并从my controller.java(如上所述)返回输出?2) 如何在不使用您的软件包(用于我的学习过程)的情况下组合两行并打印我需要的内容。我似乎在任何地方都找不到此信息。我从ParseFile中删除了您的main,并在控制器中添加了try(Reader r=new InputStreamReader(ParseFile.class.getResourceAsStream(“file”){convert(r).forEach(System.out::println);},但它不起作用
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);
        }
    }
}