简体   繁体   中英

Trim leading and trailing spaces in OpenCSV

I am using OpenCSV's CSVReader to read some comma separated values from a file. I'm not sure how to trim leading and trailing spaces. Sure, I could do String.trim() but it would be cleaner not to. In the documentation there is no such option specified.

Can you switch to SuperCSV ? It has an option to ignore surrounding spaces on its CsvPreference.Builder . It's a far superior library, IMO. If that preference doesn't do what you want, you could always extend the Tokenizer class and override readColumns . Otherwise, it looks like OpenCSV isn't very granular and would require you to extend CSVReader and override readNext . This might work:

class MyReader extends au.com.bytecode.opencsv.CSVReader {
    @Override public String[] readNext() throws IOException {
        String[] result = super.readNext();
        for (int i=0; i<result.length; i++) result[i] = result[i].trim();
        return result;
    }
}

If you are working with bean mapping and OpenCSV, I personally prefer to extend the MappingStrategy as it handles the final value assignments to their related fields. Imagine your fields are tab separated. Then you might have hard time to extend the CSVReader. Also, less coding is required.

In the following example, I am using a ColumnPositionMappingStrategy but yours can be any other MappingStrategy as populateNewBean is in the parent abstract class.

private <T> MappingStrategy<T> createMappingStrategy() {
    return new ColumnPositionMappingStrategy<T>() {
        @Override
        public T populateNewBean(String[] line) throws CsvDataTypeMismatchException, CsvConstraintViolationException,
                CsvRequiredFieldEmptyException, CsvValidationException {
            Arrays.setAll(line, (i) -> line[i].trim());
            return super.populateNewBean(line);
        }
    };
}

As you can see, each field/line is trimmed before bean is populated.

Using ngreen's idea I came up with the following working solution:

public class CSVReaderExtended extends CSVReader {

    private static final String EXP_ALPHA_AND_DIGITS = "[^a-zA-Z0-9]+";

    public CSVReaderExtended(Reader reader) {
        super(reader);
    }

    @Override
    public String[] readNext() throws IOException {
        String[] result = super.readNext();
        if (result == null)
            return null;

        for (int index = 0; index < result.length; index++) {
            result[index] = result[index].replaceAll(EXP_ALPHA_AND_DIGITS, "");
        }
        return result;
    }
}

I ended up extending CsvParser to do this

CSVParser parser = new CSVParser() {
    @Override
    protected String[] parseLine(String nextLine, boolean multi) throws IOException {
        String[] line = super.parseLine(nextLine, multi);
        Arrays.setAll(line, i -> line[i].trim());
        return line;
    }
};
MappingStrategy<R> mappingStrategy = new HeaderColumnNameMappingStrategy<>();
mappingStrategy.setType(rowType);
Reader reader = new FileReader('c:/path/to/file.csv');
CSVReader csvReader = new CSVReaderBuilder(reader).withCSVParser(csvParser).build();
CsvToBean<R> csvToBean = new CsvToBeanBuilder<R>(csvReader).withMappingStrategy(mappingStrategy).build();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM