I have a Java method that receives a CSV string of values and an integer index to reference which column in the CSV string to parse. The method returns the value associated with the integer index in the CSV string.
For example if I have a CSV string with a header and a second row with values defined as:
String csvString = "Entry #,Date Created,Date Updated, IP Address
165,8/22/13 14:46,,11.222.33.444";
and the integer index received by the method was 1, I'd expect the method to return the string "165"
And if the integer index received by the method was 2, I'd expect the method to return the string "8/22/13 14:46"
etc,...
I don't want to just split up the CSV string by commas as that could get ugly and I'm sure that there is a CSV parser that already does some parsing like this. From my Google searches it sounds like OpenCSV or the Jackson CsvMapper can do this.
I've been playing with the com.fasterxml.jackson.dataformat.csv.CsvMapper libary to parse out the appropriate column of this CSV string and here's what I have so far:
int csvFieldIndex (this is the integer index passed into my method)
String csvString = "Entry #,Date Created,Date Updated, IP Address
165,8/22/13 14:46,,11.222.33.444";
CsvSchema csvSchema = CsvSchema.emptySchema().withHeader();
ObjectReader mapper = new CsvMapper().reader(Map.class).with(csvSchema);
MappingIterator<Map<String, Object>> iter = null;
iter = mapper.readValues(csvString);
while (iter.hasNext()) {
Map<String, Object> row = iter.next();
System.out.Println("row= " + row.toString());
}
But this iterator gives me all the csv values which is not what what I want; I just want the one value associated with my integer index.
Here's the output I get when I run this snippet of code:
row= {Entry #=165, Date Created=8/22/13 14:46, Date Updated=, IP Address=11.222.33.444}
Is there a way I can use the Jackson CsvMapper to do this?
======== UPDATE: ========
Based on feedback from keshlam I was able to parse a column from a CSV with the following code:
CsvSchema csvSchema = CsvSchema.emptySchema().withHeader();
ObjectReader mapper = new CsvMapper().reader(Map.class).with(csvSchema);
MappingIterator<Map<String, Object>> iter = null;
iter = mapper.readValues(csvString);
// iterate over whole csv and store in a map
Map<String, Object> row = null;
while (iter.hasNext()) {
row = iter.next();
}
// now put the set of field names (keys) from this map into an array
String[] csvKeysArray = row.keySet().toArray(new String[0]);
int j = 0;
// loop over this array of keys and compare with csvFieldIndex
for (int i = 0; i < csvKeysArray.length; i++) {
// increment j by 1 since array index starts at 0 but input index starts at 1
j = i + 1;
if (j == csvFieldIndex) {
csvValue = row.get(csvKeysArray[i]).toString();
}
}
return csvValue;
If I'm following what you're asking, and understanding your code correctly (I've never used that CsvMapper), change the final loop to
while (iter.hasNext()) {
Map<String, Object> row = iter.next();
System.out.Println("Entry #= " + row.get("Entry #");
}
If you want to access the columns numerically rather than by name (why?), set up a mapping from number to column name and use that to retrieve the key you pass to the get() operation.