0

I have a text file that looks like following:

A
Apple
B
Bat
C
Cat

......

I need to read this text file and save it in a HashMap where an odd line is a key and the following even line is the value. For example, (A, Apple). I have tried with the following code, it doesn't work. Can someone give me a hint or advice on how I can do it?

     private HashMap<String, String> newHashMap = new HashMap<String, String>();

    Charset charset = Charset.forName("US-ASCII");

    Path path = Paths.get("file_location");
    try (BufferedReader reader = Files.newBufferedReader(path, charset)) {
        int lineCount = 0;
        String key;
        String value;

        String line = reader.readLine();
        while(line != null) {


            line = reader.readLine();

            if (lineCount % 2 == 1)
            {
            key = reader.readLine() ;

            }
            else if( lines % 2 == 0)
            {
            value = reader.readLine();

            }

            lineCount++;
           newHashMap.put(key, value);
        }
  • 1
    `"...it doesn't work"` -- tells us little of use. Please help us out here -- give us the information needed to help debug this issue. – Hovercraft Full Of Eels Feb 03 '17 at 02:34
  • Put `line = reader.readLine();` at the end of the loop. – Mordechai Feb 03 '17 at 02:35
  • By the time you reach the first readLine inside the while loop you have already read the first line outside of the loop. The first key you assign is actually from the 3rd line. You need to get your count increments and actual line reads in sync with what you want to achieve. – Alwyn Schoeman Feb 03 '17 at 02:35
  • 2
    Why not just have 2 `readLine`s every loop, and avoid all that modulus stuff? – qxz Feb 03 '17 at 02:36
  • 4
    Just read two lines, don't mess around with the `lineCount` – MadProgrammer Feb 03 '17 at 02:36
  • 1
    And don't keep on reading again inside if statements. You already have a value in `line`, use it. – Mordechai Feb 03 '17 at 02:36
  • I tried debugging with few print statements before entering the while loop and inside the while loop. Because I'm reading a line right before entering the while loop and right after entering the while loop, first 2 lines are being skipped. So, (A, Apple) is missing from the HashMap. – user6507067 Feb 03 '17 at 02:53
  • How can I read two lines at once and save line 1 value as HashMap Key and line 2 value as HashMap Value? – user6507067 Feb 03 '17 at 02:56
  • Ok. Moving the line = reader.readLine(); at the end of the loop and changing to if (lineCount == 0 || lineCount % 2 == 1), reads the line correctly. However, it seems like the key and values are not being added to the HashMap. I got "Variable Key might not have been initialized" error. – user6507067 Feb 03 '17 at 03:03
  • @user6507067 there's no need for the `lineCount` variable and if statements assuming your textfile is perfect in that it follows your format strictly (two lines per each key value pair) and the `line = reader.readLine();` should be removed and put into the loop header like I did in my answer. – Chris Gong Feb 03 '17 at 03:08

7 Answers7

2

As others have said, the if statements and lineCount variable are redundant here. The first time you call readLine is causing an issue as well because you're essentially skipping the first line in the textfile. What you should do instead is call (line = r.readLine()) != null) inside your while loop so that you have access to the read line within the loop while also being able to avoid reading after the end of the file. Also, this line inside the while loop line = reader.readLine(); is unnecessary as well. It caused you to read an extra line per iteration, and skipping it since it was never used. Besides reading in a line inside the while loop header, just read another line inside the while loop and assign each line to the right variables (key, value) like so,

while((line = reader.readLine()) != null) {
       key = line;
       value = reader.readLine();
       newHashMap.put(key, value);
}

and right outside the while loop, change String line = reader.readLine(); to

String line = "";
Chris Gong
  • 8,031
  • 4
  • 30
  • 51
1

You already have variables for key and value so use then intiially

    String key = reader.readLine();
    String value = reader.readLine();

    while(key != null && value != null) {
       newHashMap.put(key, value);
       key = reader.readLine();
       value = reader.readLine();
    }
Scary Wombat
  • 44,617
  • 6
  • 35
  • 64
1

The main problem with your code seems to be that you are not aware of the fact that calling bufferedReader.readLine() method 'n' times would read 'n' lines (if they are available). See here for more details. So what your code should look like is this :-

String key = reader.readLine();

while(key!=null){
String value = reader.readLine();
newHashMap.put(key, value);
key = reader.readLine();
}

Provided your input file has no trailing keys, the above code should work

opensam
  • 368
  • 1
  • 4
  • 10
0

Your approach is sound, just move the newHashMap.put(key, value); inside the else if block. You want to add to the map only every second line, after you have read the value.

Jim Garrison
  • 85,615
  • 20
  • 155
  • 190
0

A tweak would be to do

else if( lines % 2 == 0) {
        value = reader.readLine();
        newHashMap.put(key, value); // update when you've pair of values(key + value)
}

and none the less, the line

String line = reader.readLine();

makes you skip the first line of input with the current implementation.

Naman
  • 27,789
  • 26
  • 218
  • 353
0

If you perform a hardcoded +2 while loop, you'll remove the need of the if statements and at the same time be able to directly focus on extracting the data from each line.

The advice above is just the "cheat" version of your code. I have rewritten another version below.

First and foremost, you have read the first line with:

String line = reader.readLine();

And if we remove that,

while((line = reader.readLine()) != null) {
           newHashMap.put(line, reader.readLine());
        }

We'll shorten the code. If you look at the while loop, it actually assigns the line first, so we'll only have readLine within the put method by obtaining the even element which is in this case, the key's value.

So in short, the while loop carries the key data and the reader.readLine at the hashmap put method obtains the value data. Simple as that, you reduce the need for more memory addresses to be taken.

To further strengthen my answer, here's another overflow. Using BufferedReader to read Text File

Community
  • 1
  • 1
Nicholas
  • 1,883
  • 21
  • 39
0

You don't need to check whether lineCount is odd or even.

The description of readLine() in Java Docs, says

Reads a line of text. A line is considered to be terminated by any one of a line feed ('\n'), a carriage return ('\r'), or a carriage return followed immediately by a linefeed.

So, it reads one line at a time.

You can modify your code as:

private HashMap<String, String> newHashMap = new HashMap<String, String>();

    Charset charset = Charset.forName("US-ASCII");

    Path path = Paths.get("file_location");

    try (BufferedReader reader = Files.newBufferedReader(path, charset)) {

          String key = reader.readLine();
          String value = reader.readLine();

           while(key != null && value != null) {
              newHashMap.put(key, value);
              key = reader.readLine();
              value = reader.readLine();
}

I borrowed user @Scary Wombat's code in my answer. His code is aesthetically more pleasing, as well as ensures that you don't accidentally insert null values into the HashMap.

Community
  • 1
  • 1
Nikhil
  • 6,493
  • 10
  • 31
  • 68