简体   繁体   中英

Search for a String in a Text File using Java 8

I have a long text file that I want to read and extract some data out of it. Using JavaFX and FXML, I am using FileChooser to load the file to get the file path. My controller.java has the following:

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();


    }

Sample of text file: Note some of the file content is split between 2 lines. for Example -Ba\\ 10.10.10.3 is part of the first line.

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

I am looking for a way to search this (file) and output the following:

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

Of course you can read the input file as the stream of lines using BufferedReader.lines or Files.lines . However the tricky thing here is how to deal with the trailing "\\" . There are several possible solutions. You may write your own Reader which wraps an existing Reader and just ignores the slash followed by EOL. Alternatively you can write a custom Iterator or Spliterator which takes the BufferedReader.lines stream as the input and handles this case. I'd suggest to use my StreamEx library which already has a method for such tasks called collapse :

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

The first argument is the predicate which is applied for two adjacent lines and should return true if lines should be merged. The second argument is the function which actually merges two lines (we chop the slash via substring , then concatenate the next line).

Now you can just split the line by the whitespace and convert it to one or two output lines according to your task. Better to do it by the separate method. The whole code:

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);
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM