Search code examples
javasupercsv

Ignore extra columns in csv - SuperCSV


I am using SuperCSV to parse CSV records into Object. My CSV files have extra column in the end and I want to process only first X columns. So I define String[] mapping for first X columns and CellProcessor[] of same size. But it does not seem to work and throws exception that number of cell processors should be exactly same as number of columns.

Can somebody tell me if I am missing something. Do I need to define mapping array to have exact same columns as in five even if I don't want them?

  public CsvToBeanParser(Reader reader, Class<T> type, CsvPreference preference, CellProcessor[] cellProcessors, String[] mapping, boolean skipHeader)
        throws IOException {
    this.beanReader = new CsvBeanReader(reader, preference);
    this.mapping = mapping;
    if (skipHeader) {
        beanReader.getHeader(true);
    }
    this.cellProcessors = cellProcessors;
    this.type = type;

}

/**
 * Parse and return record.
 * 
 * @return
 * @throws Exception
 *             if there is any parsing error
 */
public T getItem() throws Exception {
    try {
        return (T) beanReader.read(type, mapping, cellProcessors);
    } catch (Exception e) {
        LOG.error("Error parsing record", e);
        throw e;
    }
}

Here are my mapping and cell processors

String[] mapping = {"column1", "column2"};
CellProcessor[] cellProcessors = {null, null};

This works for file

column1, column2
1,2

but fails for (where I want to ignore column3 )

column1, column2, column3
1,2,3

Solution

  • If you're using the header of your CSV file as the nameMapping then you'll never need to know how many columns there are, you'd just use them. If they're not appropriate for mapping (their names don't correspond with the setters in your bean) then you need to supply your own nameMapping with the correct number of elements.

    If your CSV file has a header and you know that you only ever want the first 2 columns, then you can simply provide a nameMapping array (and optionally a cell processor array) the same size as the header, but with only the first 2 elements populated.

    String[] header = beanReader.getHeader(true);
    
    // only interested in first 2 columns (rest set to null)
    String[] nameMapping = 
        Arrays.copyOf(new String[]{"column1","column2"}, header.length);
    
    // processors are optional, but you can populate these if you want
    CellProcessor[] processors = new CellProcessor[header.length];
    
    // TODO: read your CSV here...