Search code examples
javaarraylisthashmapkeyreadfile

HashMap contains a certain key but tells me it doesn't


I've been writing this code for a university activity: I need to read some lines from a .txt file, store them in a HashMap and print some results based on what was on the file. The lines are a name and a number, which are that person's name and age. For example:

Mark 23

John 32

The .txt files contain some person names, the program works out well, with one exception: The first name of the list is read, stored in the HashMap, but every time I reach for it with map.get() or map.containsKey() it tells me that key doesn't exist.

This problem happens only with the first name that was read. In the example I gave, it would happen with Mark but if I change the order of the lines, to put John first, it would happen to him, instead of Mark.

Keep in mind the key is the name of the person and the value is an object Person I create for that person.

Here are my codes:

class Person {
    private String name;
    private int age;

    //Getter
    public int getAge() {
        return this.age;
    }

    public String getName() {
        return this.name;
    }

    //Constructor
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    //toString
    @Override
    public String toString() {
        return name + " " + age;
    }
}
class OpenText {
    public static void textReader(String directory) {
        try {
            BufferedReader file = new BufferedReader(new FileReader(directory));
            String line;
            String[] lineSplit;

            while ((line = file.readLine()) != null) {
                lineSplit = line.split(" ");
                try {
                    int age = Integer.parseInt(lineSplit[1]);
                    Main.hMap.put(lineSplit[0], new Person(lineSplit[0], age));

                } catch (NumberFormatException exc) {
                    System.out.println(exc);
                }
            }

            file.close();
        } catch (IOException exc) {
            exc.printStackTrace();
        }
    }
}
public class Main {

    public static Map<String, Person> hMap = new HashMap<>();

    public static void main(String[] args) {
        OpenText.textReader("DIRECTORY OF THE FILE");
        System.out.println(hMap.keySet());
        System.out.println(hMap.values());
        System.out.println(hMap.get("John"));
    }

    // [John, Mark, Peter, Philip, Mary] 
    // [John 32, Mark 23, Peter 37, Philip 20, Mary 54] 
    // null
}

I guess it's clear that I'm just a newb to Java, but any insight would be much appreciated!

Thanks in advance!


Solution

  • Some text editors will add non printable characters to the start of the file so that when read by another text editor it know what character ending was used. e.g. https://en.wikipedia.org/wiki/Byte_order_mark

    BufferedReader doesn't do anything special with these characters but instead treats them as text you can't see.

    In your case, it means whatever word first actually has some nonprintable characters at the start which means it is not an exact match.

    To handle arbitrary BOM, you can use the following solutions.

    Byte order mark screws up file reading in Java

    I would just ensure you are not adding these in the first place.

    A simpler solution is to ignore these characters if that works for you.

    line = line.replaceAll("[\0\uFFFD]", "");
    

    btw

    BufferedReader br = new BufferedReader(
            new InputStreamReader(
                    new ByteArrayInputStream(
                            new byte[]{(byte) 0x0, (byte) 0x0, 'H', 'i', '\n'}
                    )));
    String line = br.readLine();
    System.out.println("line.length()=" + line.length());
    System.out.println(line);
    

    prints

    line.length()=4
    Hi
    

    You need to check the actual length of the String is what you expected.