Search code examples
javaopencsvunivocity

mapping particular column of a csv file with particular POJO's field


I have to map particular CSV column based on index with particular POJO attributes. Mapping will be based on a json file which will contain columnIndex and attribute name which means that for a particular columnIndex from csv file you have to map particular attribute from Pojo class. Below is a sample of json file which shows column mapping strategy with Pojo attributes.

[{"index":0,"columnname":"date"},{"index":1,"columnname":"deviceAddress"},{"index":7,"columnname":"iPAddress"},{"index":3,"columnname":"userName"},{"index":10,"columnname":"group"},{"index":5,"columnname":"eventCategoryName"},{"index":6,"columnname":"message"}]

I have tried with OpenCSV library but the challenges which i faced with that I am not able to read partial column with it. As in above json you can see that we are skipping index 2 and 4 to read from CSV file. Below is the code with openCSV file.

public static List<BaseDataModel> readCSVFile(String filePath,List<String> columnListBasedOnIndex) {
        List<BaseDataModel> csvDataModels = null;
        File myFile = new File(filePath);
        try (FileInputStream fis = new FileInputStream(myFile)) {
            final ColumnPositionMappingStrategy<BaseDataModel> strategy = new ColumnPositionMappingStrategy<BaseDataModel>();
            strategy.setType(BaseDataModel.class);


            strategy.setColumnMapping(columnListBasedOnIndex.toArray(new String[0]));

            final CsvToBeanBuilder<BaseDataModel> beanBuilder = new CsvToBeanBuilder<>(new InputStreamReader(fis));
            beanBuilder.withMappingStrategy(strategy);

            csvDataModels = beanBuilder.build().parse();

        } catch (Exception e) {
            e.printStackTrace();
        }
}


List<ColumnIndexMapping> columnIndexMappingList = dataSourceModel.getColumnMappingStrategy();
                    List<String> columnNameList = columnIndexMappingList.stream().map(ColumnIndexMapping::getColumnname)
                            .collect(Collectors.toList());

List<BaseDataModel> DataModels = Utility
                                    .readCSVFile(file.getAbsolutePath() + File.separator + fileName, columnNameList);

I have also tried with univocity but with this library how can i map csv with particular attributes. Below is the code -

CsvParserSettings settings = new CsvParserSettings();
        settings.detectFormatAutomatically(); //detects the format 
        settings.getFormat().setLineSeparator("\n");
        //extracts the headers from the input
        settings.setHeaderExtractionEnabled(true);
        settings.selectIndexes(0, 2); //rows will contain only values of columns at position 0 and 2
        CsvRoutines routines = new CsvRoutines(settings); // Can also use TSV and Fixed-width routines
        routines.parseAll(BaseDataModel.class, new File("/path/to/your.csv"));


        List<String[]> rows = new CsvParser(settings).parseAll(new File("/path/to/your.csv"), "UTF-8");

Please have a look if someone can help me in this case.


Solution

  • Author of univocity-parsers here. You can define mappings to your class attributes in code instead of annotations. Something like this:

    public class BaseDataModel {
        private String a;
        private int b;
        private String c;
        private Date d;
    }
    

    Then on your code, map the attributes to whatever column names you need:

    ColumnMapper mapper = routines.getColumnMapper();
    mapper.attributeToColumnName("a", "col1");
    mapper.attributeToColumnName("b", "col2");
    mapper.attributeToColumnName("c", "col3");
    mapper.attributeToColumnName("d", "col4");
    

    You can also use mapper.attributeToIndex("d", 3); to map attributes to a given column index.

    Hope this helps.