user6309849
user6309849

Reputation:

Compare line by line from a text file in Java

I am trying to compare lines from a text file in Java. For example, there is a text file with these lines:

temp1 am 32.5 pm 33.5
temp2 am 33.5 pm 33.5
temp3 am 32.5 pm 33.5
temp4 am 31.5 pm 35

a b c d e

a is the name of the line, b is constant(am), c is a variable, d is constant(pm), e is another variable.

It will only compare the variables -> temp1(c) to temp2(c), temp1(e) to temp2(e) etc.

When there are two or more lines with the same c(s) and e(s), it will throw FormatException.

From the example text file above, because temp1's c is the same as temp3's c and temps1's e is the same as temp3's e, it will throw FormatException.

This is what I have so far:

public static Temp read(String file) throws FormatException {
        String line = "";
        FileReader fr = new FileReader(fileName);
        Scanner scanner = new Scanner(fr);

        while(scanner.hasNextLine()) {
            String line = scanner.nextLine();
            System.out.println(line);
        }
        scanner.close();

        if () {
            throw new FormatException("Error.");

How can I make this?

Upvotes: 0

Views: 1828

Answers (4)

If I got your question right then you need to check line by line in order to find duplicates using c and e as criteria

this means, line n must be compared against all the other lines, if repeated then exception...

The suggestion will be:

Define a class that represent the element c and e of every line...

class LinePojo {

    private String c;
    private String e;
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((c == null) ? 0 : c.hashCode());
        result = prime * result + ((e == null) ? 0 : e.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        LinePojo other = (LinePojo) obj;
        if (c == null) {
            if (other.c != null)
                return false;
        } else if (!c.equals(other.c))
            return false;
        if (e == null) {
            if (other.e != null)
                return false;
        } else if (!e.equals(other.e))
            return false;
        return true;
    }

    @Override
    public String toString() {
        return "(c=" + c + ", e=" + e + ")";
    }

    public LinePojo(String c, String e) {
        this.c = c;
        this.e = e;
    }
}

then a list of that class where every line will be inserted and /or check if an element is there or not..

List<LinePojo> myList = new ArrayList<LinePojo>();

then iterate line by line

while(scanner.hasNextLine()) {
    String line = scanner.nextLine();
    String[] lineInfo = line.split(" ");
    LinePojo lp = new LinePojo(lineInfo[2], lineInfo[4]);
    if (myList.contains(lp)) {
        throw new IllegalArgumentException("there is a duplicate element");
    } else {
        myList.add(lp);
    }    
}

Upvotes: 0

Francesco Pitzalis
Francesco Pitzalis

Reputation: 2102

Here you got an example that basically includes:

First of all I would make a simple POJO representing a line info:

public class LineInfo {
    private String lineName;
    private String am;
    private String pm;

    public LineInfo(String lineName, String am, String pm) {
        this.lineName = lineName;
        this.am = am;
        this.pm = pm;
    }

    // getters and setters
}

Second I would need a pattern to validate each line and extract data from them:

//                                   group 1         group 2  group3           group 4  group 5
//                                        v               v    v                    v    v
private static final String LINE_REGEX = "(\\w+)\\s+am\\s+(\\d+(\\.\\d+)?)\\s+pm\\s+(\\d+(\\.\\d+)?)";
private static final Pattern LINE_PATTERN = Pattern.compile(LINE_REGEX);

Third I would rework the read method like this (I return void for simplicity):

public static void read(String fileName) throws FormatException {
    // collect your lines (or better the information your lines provide) in some data structure, like a List
    final List<LineInfo> lines = new ArrayList<>();

    // with this syntax your FileReader and Scanner will be closed automatically
    try (FileReader fr = new FileReader(fileName); Scanner scanner = new Scanner(fr)) {

        while (scanner.hasNextLine()) {
            final String line = scanner.nextLine();
            final Matcher matcher = LINE_PATTERN.matcher(line);

            if (matcher.find()) {
                lines.add(new LineInfo(matcher.group(1), matcher.group(2), matcher.group(4)));
            } else {
                throw new FormatException("Line \"" + line + "\" is not valid.");
            }
        }

        // recursive method
        compareLines(lines, 0);
    } catch (final IOException e) {
        e.printStackTrace();
        // or handle it in some way
    }
}

private static void compareLines(List<LineInfo> lines, int index) throws FormatException {
    // if there are no more lines return
    if (index == lines.size()) {
        return;
    }

    final LineInfo line = lines.get(index);
    for (int i = index + 1; i < lines.size(); i++) {
        final LineInfo other = lines.get(i);
        // do the check
        if (line.getAm().equals(other.getAm()) && line.getPm().equals(other.getPm())) {
            throw new FormatException(String.format("Lines #%d (%s) and #%d (%s) does not meet the requirements.",
                    index, line.getLineName(), i, other.getLineName()));
        }
    }

    // do the same thing with the next line
    compareLines(lines, index + 1);
}

Upvotes: 0

Nicolas Filotto
Nicolas Filotto

Reputation: 44965

You will need to split your lines to extract your variables and a Set to check for duplicates as next:

Set<String> ceValues = new HashSet<>();
while(scanner.hasNextLine()) {
    String line = scanner.nextLine();
    String[] values = line.split(" ");
    if (!ceValues.add(String.format("%s %s", values[2], values[4]))) {
        // The value has already been added so we throw an exception
        throw new FormatException("Error.");
    }
}

Upvotes: 3

Roel Strolenberg
Roel Strolenberg

Reputation: 2950

As I don't want to do your homework for you, let me get you started:

while(scanner.hasNextLine()) {
    String line = scanner.nextLine();
    String[] partials = line.split(" ");

    String a = partials[0]; 
    //...
    String e = partials[4];    
}

I'm splitting the line over a space as this is the only thing to split over in your case. This gives us 5 seperate strings (a through e). You will need to save them in a String[][] for later analysis but you should be able to figure out for yourself how to do this.

Try playing around with this and update your question if you're still stuck.

Upvotes: 1

Related Questions