14

HI I have a csv called test.csv . I am trying to read the csv line by line and convert the values into a hash key value pairs . Here is the code :-

public class Example {
public static void main(String[] args) throws ParseException, IOException {
    // TODO Auto-generated method stub

    BufferedReader br = new BufferedReader(new FileReader("test.csv"));
    String line =  null;
    HashMap<String,String> map = new HashMap<String, String>();

    while((line=br.readLine())!=null){
        String str[] = line.split(",");
        for(int i=0;i<str.length;i++){
            String arr[] = str[i].split(":");
            map.put(arr[0], arr[1]);
        }
    }
    System.out.println(map);
 }
}

The csv file is as follows :-

1,"testCaseName":"ACLTest","group":"All_Int","projectType":"GEN","vtName":"NEW_VT","status":"ACTIVE","canOrder":"Yes","expectedResult":"duplicateacltrue"
2,"testCaseName":"DCLAddTest","group":"India_Int","projectType":"GEN_NEW","vtName":"OLD_VT","status":"ACTIVE","canOrder":"Yes","expectedResult":"invalidfeaturesacltrue"

When I run this code I get this error :-

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 1
    Example.main(Example.java:33)

Can anyone please help me to fix the code and find out the error in my program ?

Newbie
  • 2,664
  • 7
  • 34
  • 75

8 Answers8

14

Using FasterXML's CSV package: https://github.com/FasterXML/jackson-dataformats-text/tree/master/csv

public static List<Map<String, String>> read(File file) throws JsonProcessingException, IOException {
    List<Map<String, String>> response = new LinkedList<Map<String, String>>();
    CsvMapper mapper = new CsvMapper();
    CsvSchema schema = CsvSchema.emptySchema().withHeader();
    MappingIterator<Map<String, String>> iterator = mapper.reader(Map.class)
            .with(schema)
            .readValues(file);
    while (iterator.hasNext()) {
        response.add(iterator.next());
    }
    return response;
}
Daniel
  • 8,655
  • 5
  • 60
  • 87
Kechit Goyal
  • 3,952
  • 3
  • 20
  • 21
  • I think this a better solution that OpenCSV – mmansoor Jun 08 '16 at 01:41
  • 1
    Using version 2.13.1 and getting java.lang.NoSuchMethodError: 'com.fasterxml.jackson.core.io.ContentReference com.fasterxml.jackson.dataformat.csv.CsvFactory._createContentReference(java.lang.Object)' at com.fasterxml.jackson.dataformat.csv.CsvFactory.createParser(CsvFactory.java:300) at com.fasterxml.jackson.dataformat.csv.CsvFactory.createParser(CsvFactory.java:16) at com.fasterxml.jackson.databind.ObjectReader.createParser(ObjectReader.java:1027) at com.fasterxml.jackson.databind.ObjectReader.readValues(ObjectReader.java:1953) – ka3ak Feb 11 '22 at 07:21
  • Cannot construct instance of `java.util.LinkedHashMap` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value – Roberto Pegoraro Jan 25 '23 at 13:09
11

In your String when you split it on first time only contains arr[0] as 1 nothing in arr[1] so it will cause an Exception

If you does not need the 1,2, etc.. You can look the following code:

        String str[] = line.split(",");
        for(int i=1;i<str.length;i++){
            String arr[] = str[i].split(":");
            map.put(arr[0], arr[1]);
        }
Rakesh KR
  • 6,357
  • 5
  • 40
  • 55
3

The problem is that when you split your str, the first element in each line is alone (i.e 1 and 2). So arr only contains ["1"], and hence arr[1] doesn't exists.

I.e for the example input :

1,"testCaseName":"ACLTest"

split by , => str contains {1, testCaseName:ACLTest}
split by : at the first iteration => arr contains {1}

Example :

String s = "1,testCaseName:ACLTest";
String str[] = s.split(",");
System.out.println(Arrays.toString(str));
for(String p : str){
    String arr[] = p.split(":");
    System.out.println(Arrays.toString(arr));
}

Output :

[1, testCaseName:ACLTest]
[1] //<- here arr[1] doesn't exists, you only have arr[0] and hence the ArrayIndexOutOfBoundsException when trying to access arr[1]
[testCaseName, ACLTest]


To fix your code (if you don't want to use a CSV parser), make your loop starting at 1 :
for(int i=1;i<str.length;i++){
      String arr[] = str[i].split(":");
      map.put(arr[0], arr[1]);
}


Another problem is that the HashMap use the hashCode of the keys to store the (key, value) pairs.

So when insering "testCaseName":"ACLTest" and "testCaseName":"DCLAddTest", the first value will be erased and replace by the second one :

Map<String, String> map = new HashMap<>();
map.put("testCaseName","ACLTest");
map.put("testCaseName","DCLAddTest");
System.out.println(map);

Output :

{testCaseName=DCLAddTest}

So you have to fix that too.

Alexis C.
  • 91,686
  • 21
  • 171
  • 177
0

Look at the output of the call String arr[] = str[i].split(":"); arr[1] does not exists for the first element in your CSV file which happens to be 1, 2... You can start the loop with int i=0 to fix this issue.

Marek Puchalski
  • 3,286
  • 2
  • 26
  • 35
0

String.split is rubbish for parsing CSV. Either use the Guava Splitter or a proper CSV parser. You can parse CSV into beans using the Jackson CSV mapper like this:

public class CSVPerson{
  public String firstname;
  public String lastname;
  //etc
}

CsvMapper mapper = new CsvMapper();
CsvSchema schema = CsvSchema.emptySchema().withHeader().withColumnSeparator(delimiter);
MappingIterator<CSVPerson> it = = mapper.reader(CSVPerson).with(schema).readValues(input);
while (it.hasNext()){
  CSVPerson row = it.next();
}

more info at http://demeranville.com/how-not-to-parse-csv-using-java/

tom
  • 2,704
  • 16
  • 28
0

Beside the problem you have with the first number which its not a pair and its causing the Exception, you will not want to use Hashmap, since hashmap use a unique key, so line 2 will replace values from line 1.

You should use a MultiMap, or a List of pairs in this case.

cri_sys
  • 472
  • 1
  • 5
  • 17
0
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.*;
public class Example {


    public static void main(String[] args) {

        String csvFile = "test.csv";
        String line = "";
        String cvsSplitBy = ",";
        HashMap<String, String> list = new HashMap<>();
        try (BufferedReader br = new BufferedReader(new FileReader(csvFile))) {

            while ((line = br.readLine()) != null) {

                // use comma as separator
                String[] country = line.split(cvsSplitBy);

                //System.out.println(country[0] +"  "  + country[1]);
                list.put(country[0], country[1]);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println(list);

    }
   // enter code here

}
Ram Ghadiyaram
  • 28,239
  • 13
  • 95
  • 121
dimuthu93
  • 3
  • 1
-1

using openCSV would be one way to do it

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

import au.com.bytecode.opencsv.CSVReader;

public class CsvFileReader {
    public static void main(String[] args) {

        try {
            System.out.println("\n**** readLineByLineExample ****");
            String csvFilename = "C:/Users/hussain.a/Desktop/sample.csv";
            CSVReader csvReader = new CSVReader(new FileReader(csvFilename));
            String[] col = null;
            while ((col = csvReader.readNext()) != null) 
            {
                System.out.println(col[0] );
                //System.out.println(col[0]);
            }
            csvReader.close();
        }
        catch(ArrayIndexOutOfBoundsException ae)
        {
            System.out.println(ae+" : error here");
        }catch (FileNotFoundException e) 
        {
            System.out.println("asd");
            e.printStackTrace();
        } catch (IOException e) {
            System.out.println("");
            e.printStackTrace();
        }
    }
}

the jar is available here