Java read txt file to hashmap, split by ":"

61,919

Solution 1

Read your file line-by-line using a BufferedReader, and for each line perform a split on the first occurrence of : within the line (and if there is no : then we ignore that line).

Here is some example code - it avoids the use of Scanner (which has some subtle behaviors and imho is actually more trouble than its worth).

public static void main( String[] args ) throws IOException
{
    String filePath = "test.txt";
    HashMap<String, String> map = new HashMap<String, String>();

    String line;
    BufferedReader reader = new BufferedReader(new FileReader(filePath));
    while ((line = reader.readLine()) != null)
    {
        String[] parts = line.split(":", 2);
        if (parts.length >= 2)
        {
            String key = parts[0];
            String value = parts[1];
            map.put(key, value);
        } else {
            System.out.println("ignoring line: " + line);
        }
    }

    for (String key : map.keySet())
    {
        System.out.println(key + ":" + map.get(key));
    }
    reader.close();
}

Solution 2

The below will work in java 8.

The .filter(s -> s.matches("^\\w+:\\w+$")) will mean it only attempts to work on line in the file which are two strings separated by :, obviously fidling with this regex will change what it will allow through.

The .collect(Collectors.toMap(k -> k.split(":")[0], v -> v.split(":")[1])) will work on any lines which match the previous filter, split them on : then use the first part of that split as the key in a map entry, then the second part of that split as the value in the map entry.

import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Map;
import java.util.stream.Collectors;

public class Foo {

    public static void main(String[] args) throws IOException {
        String filePath = "src/main/resources/somefile.txt";

        Path path = FileSystems.getDefault().getPath(filePath);
        Map<String, String> mapFromFile = Files.lines(path)
            .filter(s -> s.matches("^\\w+:\\w+"))
            .collect(Collectors.toMap(k -> k.split(":")[0], v -> v.split(":")[1]));
    }
}

Solution 3

One more JDK 1.8 implementation.

I suggest using try-with-resources and forEach iterator with putIfAbsent() method to avoid java.lang.IllegalStateException: Duplicate key value if there are some duplicate values in the file.

FileToHashMap.java

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Map;
import java.util.HashMap;
import java.util.stream.Stream;

public class FileToHashMap {
    public static void main(String[] args) throws IOException {
        String delimiter = ":";
        Map<String, String> map = new HashMap<>();

        try(Stream<String> lines = Files.lines(Paths.get("in.txt"))){
            lines.filter(line -> line.contains(delimiter)).forEach(
                line -> map.putIfAbsent(line.split(delimiter)[0], line.split(delimiter)[1])
            );
        }

        System.out.println(map);    
    }
}

in.txt

Key1:value 1
Key1:duplicate key
Key2:value 2
Key3:value 3

The output is:

{Key1=value 1, Key2=value 2, Key3=value 3}
Share:
61,919
Casper TL
Author by

Casper TL

Studying computer science (2014-2017) Programming language: Java

Updated on May 02, 2021

Comments

  • Casper TL
    Casper TL about 3 years

    I have a txt file with the form:

    Key:value
    Key:value
    Key:value
    ...
    

    I want to put all the keys with their value in a hashMap that I've created. How do I get a FileReader(file) or Scanner(file) to know when to split up the keys and values at the colon (:) ? :-)

    I've tried:

    Scanner scanner = new scanner(file).useDelimiter(":");
    HashMap<String, String> map = new Hashmap<>();
    
    while(scanner.hasNext()){
        map.put(scanner.next(), scanner.next());
    }
    
  • Casper TL
    Casper TL about 9 years
    That worked just as i wanted! Thank you very much for your detailed example! :-)
  • Tom
    Tom about 9 years
    Is closing resources overrated these days? No one seems to do that anymore.
  • trooper
    trooper about 9 years
    definitely overrated </snark> It was just an example Tom, but your point is well taken. Please feel free to modify the answer to add a try/finally if you think it deserves it.
  • Björn Lindqvist
    Björn Lindqvist about 5 years
    Alternatively, one can use Files.lines(Paths.get(filePath))...
  • tomasantunes
    tomasantunes about 3 years
    Please provide some explanation.