I have a CSV file with the following columns: id
, fname
, telephone
, lname
, address
.
I have a P
Use @CsvIgnore annotation above the field which need not to be written to csv file.
Recent versions of OpenCSV deprecate the method parse(X, Y)
and it's recommenced to use BeanBuilder instead, so the top answer is out of date.
try {
CsvToBeanBuilder<PersonCSV> beanBuilder = new CsvToBeanBuilder<>(new InputStreamReader(new FileInputStream("your.csv")));
beanBuilder.withType(PersonCSV.class);
// build methods returns a list of Beans
beanBuilder.build().parse().forEach(e -> log.error(e.toString()));
} catch (FileNotFoundException e) {
log.error(e.getMessage(), e);
}
This methods allows you to clean up the code and remove MappingStrategy (you can still use it if you like spaghetti), so you can annotate your CSV class as follows:
@CsvDate("dd/MM/yyyy hh:mm:ss")
@CsvBindByName(column = "Time Born", required = true)
private Date birthDate;
SimpleFlatMapper can do that easily see Getting Started csv using the headers of the csv or by manually specifying which columns map to what property.
CsvParser
.mapTo(MyObject.class)
.forEach(file, System.out::println);
With opencsv, you can create a generic function like :
public static <T> void csvWriterUtil(Class<T> beanClass, List<T> data, String outputFile, String[] columMapping){
try{
Writer writer = new BufferedWriter(new FileWriter(outputFile));
ColumnPositionMappingStrategy<T> strategy = new ColumnPositionMappingStrategy<>();
strategy.setType(beanClass);
strategy.setColumnMapping(columMapping);
StatefulBeanToCsv<T> statefulBeanToCsv =new StatefulBeanToCsvBuilder<T>(writer)
.withMappingStrategy(strategy)
.build();
writer.write(String.join(",",columMapping)+"\n");
statefulBeanToCsv.write(data);
writer.close();
} catch (IOException e) {
e.printStackTrace();
} catch (CsvRequiredFieldEmptyException e) {
e.printStackTrace();
} catch (CsvDataTypeMismatchException e) {
e.printStackTrace();
}
}
Here you can pass only required columns through columMapping parameter. Code example is available in https://github.com/soumya-kole/JavaUtils/tree/master/CsvUtil
Here is a nice way to do use OpenCSV to do the mapping to POJO generically:
protected <T> List<T> mapToCSV(String csvContent, Class<T> mapToClass) {
CsvToBean<T> csvToBean = new CsvToBean<T>();
Map<String, String> columnMapping = new HashMap<>();
Arrays.stream(mapToClass.getDeclaredFields()).forEach(field -> {
columnMapping.put(field.getName(), field.getName());
});
HeaderColumnNameTranslateMappingStrategy<T> strategy = new HeaderColumnNameTranslateMappingStrategy<T>();
strategy.setType(mapToClass);
strategy.setColumnMapping(columnMapping);
CSVReader reader = new CSVReader(new StringReader(csvContent));
return csvToBean.parse(strategy, reader);
}
public static class MyPojo {
private String foo, bar;
public void setFoo(String foo) {
this.foo = foo;
}
public void setBar(String bar) {
this.bar = bar;
}
}
Then from your test you can use:
List<MyPojo> list = mapToCSV(csvContent, MyPojo.class);
Have a look at jcsvdao, https://github.com/eric-mckinley/jcsvdao/ , uses hibernate style mapping files and can handle 1to1 and 1toMany relations. Good if you dont own the csv files as has flexible matching strategies.