Java OpenCSV:如何使用自定义列标题和自定义列位置从POJO创建CSV文件?
我创建了一个MappingsBean类,其中指定了CSV文件的所有列。接下来,我解析XML文件并创建MappingBean列表。然后我将数据作为报告写入CSV文件 我正在使用以下注释:Java OpenCSV:如何使用自定义列标题和自定义列位置从POJO创建CSV文件?,java,xml,csv,opencsv,Java,Xml,Csv,Opencsv,我创建了一个MappingsBean类,其中指定了CSV文件的所有列。接下来,我解析XML文件并创建MappingBean列表。然后我将数据作为报告写入CSV文件 我正在使用以下注释: public class MappingsBean { @CsvBindByName(column = "TradeID") @CsvBindByPosition(position = 0) private String tradeId; @CsvBindByName(colu
public class MappingsBean {
@CsvBindByName(column = "TradeID")
@CsvBindByPosition(position = 0)
private String tradeId;
@CsvBindByName(column = "GWML GUID", required = true)
@CsvBindByPosition(position = 1)
private String gwmlGUID;
@CsvBindByName(column = "MXML GUID", required = true)
@CsvBindByPosition(position = 2)
private String mxmlGUID;
@CsvBindByName(column = "GWML File")
@CsvBindByPosition(position = 3)
private String gwmlFile;
@CsvBindByName(column = "MxML File")
@CsvBindByPosition(position = 4)
private String mxmlFile;
@CsvBindByName(column = "MxML Counterparty")
@CsvBindByPosition(position = 5)
private String mxmlCounterParty;
@CsvBindByName(column = "GWML Counterparty")
@CsvBindByPosition(position = 6)
private String gwmlCounterParty;
}
然后我使用statefulbeantocvs
类写入CSV文件:
File reportFile = new File(reportOutputDir + "/" + REPORT_FILENAME);
Writer writer = new PrintWriter(reportFile);
StatefulBeanToCsv<MappingsBean> beanToCsv = new
StatefulBeanToCsvBuilder(writer).build();
beanToCsv.write(makeFinalMappingBeanList());
writer.close();
File reportFile=新文件(reportOutputDir+“/”+报告文件名);
Writer Writer=新的PrintWriter(报告文件);
StatefulBeanToCsv beanToCsv=新建
StatefulBeanToCsvBuilder(writer.build();
write(makeFinalMappingBeanList());
writer.close();
这种方法的问题是,如果我使用@CsvBindByPosition(position=0)
来控制
位置,则我无法生成列名。如果使用@CsvBindByName(column=“TradeID”)
,则无法设置列的位置
是否有一种方法可以同时使用这两种注释,以便创建具有列标题的CSV文件并控制列位置
问候,,
Vikram Pathania我也有类似的问题。另外,OpenCSV中没有内置功能,允许使用自定义列名和排序将bean写入CSV OpenCSV开箱即用中提供了两种主要的映射策略:
:允许基于自定义名称将CVS文件列映射到bean字段;将bean写入CSV时,这允许更改列标题名称,但我们无法控制列顺序HeaderColumnNameMappingStrategy
:允许根据列顺序将CSV文件列映射到bean字段;将bean写入CSV时,我们可以控制列顺序,但得到一个空的标题(实现返回ColumnPositionMappingStrategy
作为标题)新字符串[0]
MappingStrategy
第一个解决方案:快速、简单但硬编码
创建自定义映射策略:
class CustomMappingStrategy<T> extends ColumnPositionMappingStrategy<T> {
private static final String[] HEADER = new String[]{"TradeID", "GWML GUID", "MXML GUID", "GWML File", "MxML File", "MxML Counterparty", "GWML Counterparty"};
@Override
public String[] generateHeader() {
return HEADER;
}
}
在MappingsBean
类中,我们留下了CsvBindByPosition
annotations-来控制顺序(在这个解决方案中CsvBindByName
不需要注释)。由于自定义映射策略,标题列名包含在生成的CSV文件中
此解决方案的缺点是,当我们通过CsvBindByPosition
注释更改列顺序时,我们还必须在自定义映射策略中手动更改标题
常量
第二个解决方案:更灵活
第一个解决方案是可行的,但对我不好。基于映射策略的内置实现
我提出了另一个实现:
class CustomMappingStrategy<T> extends ColumnPositionMappingStrategy<T> {
@Override
public String[] generateHeader() {
final int numColumns = findMaxFieldIndex();
if (!isAnnotationDriven() || numColumns == -1) {
return super.generateHeader();
}
header = new String[numColumns + 1];
BeanField beanField;
for (int i = 0; i <= numColumns; i++) {
beanField = findField(i);
String columnHeaderName = extractHeaderName(beanField);
header[i] = columnHeaderName;
}
return header;
}
private String extractHeaderName(final BeanField beanField) {
if (beanField == null || beanField.getField() == null || beanField.getField().getDeclaredAnnotationsByType(CsvBindByName.class).length == 0) {
return StringUtils.EMPTY;
}
final CsvBindByName bindByNameAnnotation = beanField.getField().getDeclaredAnnotationsByType(CsvBindByName.class)[0];
return bindByNameAnnotation.column();
}
}
类CustomMappingStrategy扩展了ColumnPositionMappingStrategy{
@凌驾
公共字符串[]generateHeader(){
final int numColumns=findMaxFieldIndex();
如果(!isAnnotationDriven()| | numColumns===-1){
返回super.generateHeader();
}
header=新字符串[numColumns+1];
豆田豆田;
对于(int i=0;i如果您没有getDeclaredAnnotationsByType方法,但需要原始字段名的名称:
beanField.getField().getName()
公共类CustomMappingStrategy扩展了ColumnPositionMappingStrategy{
@凌驾
公共字符串[]generateHeader(){
final int numColumns=findMaxFieldIndex();
如果(!isAnnotationDriven()| | numColumns===-1){
返回super.generateHeader();
}
header=新字符串[numColumns+1];
豆田豆田;
对于(int i=0;i已更正上述答案,以与较新版本匹配
package csvpojo;
import org.apache.commons.lang3.StringUtils;
import com.opencsv.bean.BeanField;
import com.opencsv.bean.ColumnPositionMappingStrategy;
import com.opencsv.bean.CsvBindByName;
import com.opencsv.exceptions.CsvRequiredFieldEmptyException;
class CustomMappingStrategy<T> extends ColumnPositionMappingStrategy<T> {
@Override
public String[] generateHeader(T bean) throws CsvRequiredFieldEmptyException {
super.setColumnMapping(new String[ FieldUtils.getAllFields(bean.getClass()).length]);
final int numColumns = findMaxFieldIndex();
if (!isAnnotationDriven() || numColumns == -1) {
return super.generateHeader(bean);
}
String[] header = new String[numColumns + 1];
BeanField<T> beanField;
for (int i = 0; i <= numColumns; i++) {
beanField = findField(i);
String columnHeaderName = extractHeaderName(beanField);
header[i] = columnHeaderName;
}
return header;
}
private String extractHeaderName(final BeanField<T> beanField) {
if (beanField == null || beanField.getField() == null
|| beanField.getField().getDeclaredAnnotationsByType(CsvBindByName.class).length == 0) {
return StringUtils.EMPTY;
}
final CsvBindByName bindByNameAnnotation = beanField.getField()
.getDeclaredAnnotationsByType(CsvBindByName.class)[0];
return bindByNameAnnotation.column();
}
}
感谢这个线程,它对我真的很有用…我对提供的解决方案进行了一点增强,以便也接受POJO,其中一些字段没有注释(不意味着读/写):
公共类ColumnAndNameMappingStrategy扩展了ColumnPositionMappingStrategy{
@凌驾
公共字符串[]generateHeader(T bean)抛出CsvRequiredFieldEmptyException{
setColumnMapping(新字符串[getAnnotatedFields(bean)]);
final int numColumns=getAnnotatedFields(bean);
final int totalFieldNum=findMaxFieldIndex();
如果(!isAnnotationDriven()| | numColumns===-1){
返回super.generateHeader(bean);
}
字符串[]头=新字符串[numColumns];
豆田豆田;
对于(int i=0;i我希望实现双向导入/导出-能够将生成的CSV导入回POJO,反之亦然
我无法为此使用@CsvBindByPosition,因为在这种情况下,已自动选择-ColumnPositionMappingStrategy。每个文档:
我用什么来实现目标:
用于预定义字符串排序的自定义比较器:
public class OrderedComparatorIgnoringCase implements Comparator<String> {
private List<String> predefinedOrder;
public OrderedComparatorIgnoringCase(String[] predefinedOrder) {
this.predefinedOrder = new ArrayList<>();
for (String item : predefinedOrder) {
this.predefinedOrder.add(item.toLowerCase());
}
}
@Override
public int compare(String o1, String o2) {
return predefinedOrder.indexOf(o1.toLowerCase()) - predefinedOrder.indexOf(o2.toLowerCase());
}
}
public static void main(String[] args) throws Exception {
//omitted code from writing
String csv = convertToCsv(localBusinessTrainingPairsDTO, mappingStrategy);
//Exported CSV should be compatible for further import
File temp = File.createTempFile("tempTrainingPairs", ".csv");
temp.deleteOnExit();
BufferedWriter bw = new BufferedWriter(new FileWriter(temp));
bw.write(csv);
bw.close();
MultipartFile multipartFile = new MockMultipartFile("tempTrainingPairs.csv", new FileInputStream(temp));
List<LocalBusinessTrainingPairDTO> localBusinessTrainingPairDTOList = convertFromCsv(multipartFile, LocalBusinessTrainingPairDTO.class);
}
CustomBeanToCSVMappingStrategy<Pojo> mappingStrategy = new CustomBeanToCSVMappingStrategy<>();
mappingStrategy.setType(Pojo.class);
StatefulBeanToCsv<Pojo> beanToCsv = new StatefulBeanToCsvBuilder<Pojo>(writer)
.withSeparator(CSVWriter.DEFAULT_SEPARATOR)
.withMappingStrategy(mappingStrategy)
.build();
beanToCsv.write(pojoList);
公共类OrderedComparatorIgnoringCase实现了Comparator{
私有列表预定义顺序;
public OrderedComparatorIgnoringCase(字符串[]预定义顺序){
this.predefinedOrder=新的ArrayList();
for(字符串项:预定义订单){
this.predefinedOrder.add(item.toLowerCase());
}
}
@凌驾
公共整数比较(字符串o1、字符串o2){
返回预定义的order.indexOf(o1.toLowerCase())-predefinedOrder.indexOf(o2.toLowerCase());
}
}
POJO的有序写作(对初始问题的回答)
public static void main(String[] args) throws Exception {
List<LocalBusinessTrainingPairDTO> localBusinessTrainingPairsDTO = new ArrayList<>();
LocalBusinessTrainingPairDTO localBusinessTrainingPairDTO = new LocalBusinessTrainingPairDTO();
localBusinessTrainingPairDTO.setLeftId(1);
localBusinessTrainingPairDTO.setLeftName("leftName");
localBusinessTrainingPairDTO.setRightId(2);
localBusinessTrainingPairDTO.setRightName("rightName");
localBusinessTrainingPairsDTO.add(localBusinessTrainingPairDTO);
//Creating HeaderColumnNameMappingStrategy
HeaderColumnNameMappingStrategy<LocalBusinessTrainingPairDTO> mappingStrategy = new HeaderColumnNameMappingStrategy<>();
mappingStrategy.setType(LocalBusinessTrainingPairDTO.class);
//Setting predefined order using String comparator
mappingStrategy.setColumnOrderOnWrite(new OrderedComparatorIgnoringCase(LocalBusinessTrainingPairDTO.FIELDS_ORDER));
String csv = convertToCsv(localBusinessTrainingPairsDTO, mappingStrategy);
System.out.println(csv);
}
publicstaticvoidmain(字符串[]args)引发异常{
列出localBusinessTrainingPairsDTO=new ArrayList();
LocalBusinessTrainingPairDTO LocalBusinessTrainingPairDTO=新建LocalBusinessTrainingPairDTO();
localBusinessTrainingPairDTO.setLeftId(1);
localBusinessTrainingPairDTO.setLeftName(“leftName”);
localBusinessTrainingPairDTO.setRightId(2);
localBusinessTra
public class ColumnAndNameMappingStrategy<T> extends ColumnPositionMappingStrategy<T> {
@Override
public String[] generateHeader(T bean) throws CsvRequiredFieldEmptyException {
super.setColumnMapping(new String[ getAnnotatedFields(bean)]);
final int numColumns = getAnnotatedFields(bean);
final int totalFieldNum = findMaxFieldIndex();
if (!isAnnotationDriven() || numColumns == -1) {
return super.generateHeader(bean);
}
String[] header = new String[numColumns];
BeanField<T> beanField;
for (int i = 0; i <= totalFieldNum; i++) {
beanField = findField(i);
if (isFieldAnnotated(beanField.getField())) {
String columnHeaderName = extractHeaderName(beanField);
header[i] = columnHeaderName;
}
}
return header;
}
private int getAnnotatedFields(T bean) {
return (int) Arrays.stream(FieldUtils.getAllFields(bean.getClass()))
.filter(this::isFieldAnnotated)
.count();
}
private boolean isFieldAnnotated(Field f) {
return f.isAnnotationPresent(CsvBindByName.class) || f.isAnnotationPresent(CsvCustomBindByName.class);
}
private String extractHeaderName(final BeanField beanField) {
if (beanField == null || beanField.getField() == null) {
return StringUtils.EMPTY;
}
Field field = beanField.getField();
if (field.getDeclaredAnnotationsByType(CsvBindByName.class).length != 0) {
final CsvBindByName bindByNameAnnotation = field.getDeclaredAnnotationsByType(CsvBindByName.class)[0];
return bindByNameAnnotation.column();
}
if (field.getDeclaredAnnotationsByType(CsvCustomBindByName.class).length != 0) {
final CsvCustomBindByName bindByNameAnnotation = field.getDeclaredAnnotationsByType(CsvCustomBindByName.class)[0];
return bindByNameAnnotation.column();
}
return StringUtils.EMPTY;
}
HeaderColumnNameMappingStrategy
mappingStrategy.setColumnOrderOnWrite(Comparator<String> writeOrder)
import com.opencsv.CSVWriter;
import com.opencsv.bean.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
import java.util.List;
public class CsvUtils {
private CsvUtils() {
}
public static <T> String convertToCsv(List<T> entitiesList, MappingStrategy<T> mappingStrategy) throws Exception {
try (Writer writer = new StringWriter()) {
StatefulBeanToCsv<T> beanToCsv = new StatefulBeanToCsvBuilder<T>(writer)
.withMappingStrategy(mappingStrategy)
.withQuotechar(CSVWriter.NO_QUOTE_CHARACTER)
.build();
beanToCsv.write(entitiesList);
return writer.toString();
}
}
@SuppressWarnings("unchecked")
public static <T> List<T> convertFromCsv(MultipartFile file, Class clazz) throws IOException {
try (Reader reader = new BufferedReader(new InputStreamReader(file.getInputStream()))) {
CsvToBean<T> csvToBean = new CsvToBeanBuilder<T>(reader).withType(clazz).build();
return csvToBean.parse();
}
}
}
public class LocalBusinessTrainingPairDTO {
//this is used for CSV columns ordering on exporting LocalBusinessTrainingPairs
public static final String[] FIELDS_ORDER = {"leftId", "leftName", "rightId", "rightName"};
@CsvBindByName(column = "leftId")
private int leftId;
@CsvBindByName(column = "leftName")
private String leftName;
@CsvBindByName(column = "rightId")
private int rightId;
@CsvBindByName(column = "rightName")
private String rightName;
// getters/setters omitted, do not forget to add them
}
public class OrderedComparatorIgnoringCase implements Comparator<String> {
private List<String> predefinedOrder;
public OrderedComparatorIgnoringCase(String[] predefinedOrder) {
this.predefinedOrder = new ArrayList<>();
for (String item : predefinedOrder) {
this.predefinedOrder.add(item.toLowerCase());
}
}
@Override
public int compare(String o1, String o2) {
return predefinedOrder.indexOf(o1.toLowerCase()) - predefinedOrder.indexOf(o2.toLowerCase());
}
}
public static void main(String[] args) throws Exception {
List<LocalBusinessTrainingPairDTO> localBusinessTrainingPairsDTO = new ArrayList<>();
LocalBusinessTrainingPairDTO localBusinessTrainingPairDTO = new LocalBusinessTrainingPairDTO();
localBusinessTrainingPairDTO.setLeftId(1);
localBusinessTrainingPairDTO.setLeftName("leftName");
localBusinessTrainingPairDTO.setRightId(2);
localBusinessTrainingPairDTO.setRightName("rightName");
localBusinessTrainingPairsDTO.add(localBusinessTrainingPairDTO);
//Creating HeaderColumnNameMappingStrategy
HeaderColumnNameMappingStrategy<LocalBusinessTrainingPairDTO> mappingStrategy = new HeaderColumnNameMappingStrategy<>();
mappingStrategy.setType(LocalBusinessTrainingPairDTO.class);
//Setting predefined order using String comparator
mappingStrategy.setColumnOrderOnWrite(new OrderedComparatorIgnoringCase(LocalBusinessTrainingPairDTO.FIELDS_ORDER));
String csv = convertToCsv(localBusinessTrainingPairsDTO, mappingStrategy);
System.out.println(csv);
}
public static void main(String[] args) throws Exception {
//omitted code from writing
String csv = convertToCsv(localBusinessTrainingPairsDTO, mappingStrategy);
//Exported CSV should be compatible for further import
File temp = File.createTempFile("tempTrainingPairs", ".csv");
temp.deleteOnExit();
BufferedWriter bw = new BufferedWriter(new FileWriter(temp));
bw.write(csv);
bw.close();
MultipartFile multipartFile = new MockMultipartFile("tempTrainingPairs.csv", new FileInputStream(temp));
List<LocalBusinessTrainingPairDTO> localBusinessTrainingPairDTOList = convertFromCsv(multipartFile, LocalBusinessTrainingPairDTO.class);
}
private static class CustomMappingStrategy<T> extends ColumnPositionMappingStrategy<T> {
String[] header;
public CustomMappingStrategy(String[] cols) {
header = cols;
}
@Override
public String[] generateHeader(T bean) throws CsvRequiredFieldEmptyException {
return header;
}
}
String[] columns = new String[]{"Name", "Age", "Company", "Salary"};
CustomMappingStrategy<Employee> mappingStrategy = new CustomMappingStrategy<Employee>(columns);
"COLUMN 1","COLUMN 2","COLUMN 3",...
"value 1a","value 2a","value 3a",...
"value 1b","value 2b","value 3b",...
/**
* Custom OpenCSV [ColumnPositionMappingStrategy] that allows for a header line to be generated from a target CSV
* bean model class using the following annotations when present:
* * [CsvBindByName]
* * [CsvCustomBindByName]
*/
class CustomMappingStrategy<T>(private val beanType: Class<T>) : ColumnPositionMappingStrategy<T>() {
init {
setType(beanType)
setColumnMapping(*getAnnotatedFields().map { it.extractHeaderName() }.toTypedArray())
}
override fun generateHeader(bean: T): Array<String> = columnMapping
private fun getAnnotatedFields() = beanType.declaredFields.filter { it.isAnnotatedByName() }.toList()
private fun Field.isAnnotatedByName() = isAnnotationPresent(CsvBindByName::class.java) || isAnnotationPresent(CsvCustomBindByName::class.java)
private fun Field.extractHeaderName() =
getAnnotation(CsvBindByName::class.java)?.column ?: getAnnotation(CsvCustomBindByName::class.java)?.column ?: EMPTY
}
private fun csvBuilder(writer: Writer) =
StatefulBeanToCsvBuilder<MappingsBean>(writer)
.withSeparator(ICSVWriter.DEFAULT_SEPARATOR)
.withMappingStrategy(CustomMappingStrategy(MappingsBean::class.java))
.withApplyQuotesToAll(false)
.build()
// Kotlin try-with-resources construct
PrintWriter(File("$reportOutputDir/$REPORT_FILENAME")).use { writer ->
csvBuilder(writer).write(makeFinalMappingBeanList())
}
data class MappingsBean(
@field:CsvBindByName(column = "TradeID")
@field:CsvBindByPosition(position = 0, required = true)
private val tradeId: String,
@field:CsvBindByName(column = "GWML GUID", required = true)
@field:CsvBindByPosition(position = 1)
private val gwmlGUID: String,
@field:CsvBindByName(column = "MXML GUID", required = true)
@field:CsvBindByPosition(position = 2)
private val mxmlGUID: String,
@field:CsvBindByName(column = "GWML File")
@field:CsvBindByPosition(position = 3)
private val gwmlFile: String? = null,
@field:CsvBindByName(column = "MxML File")
@field:CsvBindByPosition(position = 4)
private val mxmlFile: String? = null,
@field:CsvBindByName(column = "MxML Counterparty")
@field:CsvBindByPosition(position = 5)
private val mxmlCounterParty: String? = null,
@field:CsvBindByName(column = "GWML Counterparty")
@field:CsvBindByPosition(position = 6)
private val gwmlCounterParty: String? = null
)
public class CustomMappingStrategy<T> extends ColumnPositionMappingStrategy<T> {
@Override
public String[] generateHeader(T bean) throws CsvRequiredFieldEmptyException {
super.setColumnMapping(new String[ FieldUtils.getAllFields(bean.getClass()).length]);
final int numColumns = findMaxFieldIndex();
if (!isAnnotationDriven() || numColumns == -1) {
return super.generateHeader(bean);
}
String[] header = new String[numColumns + 1];
BeanField<T> beanField;
for (int i = 0; i <= numColumns; i++) {
beanField = findField(i);
String columnHeaderName = extractHeaderName(beanField);
header[i] = columnHeaderName;
}
return header;
}
private String extractHeaderName(final BeanField<T> beanField) {
if (beanField == null || beanField.getField() == null
|| beanField.getField().getDeclaredAnnotationsByType(CsvBindByName.class).length == 0) {
return StringUtils.EMPTY;
}
final CsvBindByName bindByNameAnnotation = beanField.getField()
.getDeclaredAnnotationsByType(CsvBindByName.class)[0];
return bindByNameAnnotation.column();
}
}
public class Customer{
@CsvBindByPosition(position=1)
@CsvBindByName(column="CUSTOMER", required = true)
private String customer;
}
List<T> data = getEmployeeRecord();
CustomMappingStrategy custom = new CustomMappingStrategy();
custom.setType(Employee.class);
StatefulBeanToCsv<T> writer = new StatefulBeanToCsvBuilder<T>(response.getWriter())
.withQuotechar(CSVWriter.NO_QUOTE_CHARACTER)
.withSeparator('|')
.withOrderedResults(false)
.withMappingStrategy(custom)
.build();
writer.write(reportData);
public class MappingBean {
@CsvBindByName(column = "column_a")
private String columnA;
@CsvBindByName(column = "column_b")
private String columnB;
@CsvBindByName(column = "column_c")
private String columnC;
// getters and setters
}
import org.apache.commons.collections4.comparators.FixedOrderComparator;
var mappingStrategy = new HeaderColumnNameMappingStrategy<MappingBean>();
mappingStrategy.setType(MappingBean.class);
mappingStrategy.setColumnOrderOnWrite(new FixedOrderComparator<>("COLUMN_C", "COLUMN_B", "COLUMN_A"));
var sbc = new StatefulBeanToCsvBuilder<MappingBean>(writer)
.withMappingStrategy(mappingStrategy)
.build();
import com.opencsv.bean.BeanField;
import com.opencsv.bean.ColumnPositionMappingStrategy;
import com.opencsv.bean.CsvBindByName;
import com.opencsv.exceptions.CsvRequiredFieldEmptyException;
import org.apache.commons.lang3.StringUtils;
class CustomMappingStrategy<T> extends ColumnPositionMappingStrategy<T> {
@Override
public String[] generateHeader(T bean) throws CsvRequiredFieldEmptyException {
final int numColumns = getFieldMap().values().size();
super.generateHeader(bean);
String[] header = new String[numColumns];
BeanField beanField;
for (int i = 0; i < numColumns; i++) {
beanField = findField(i);
String columnHeaderName = extractHeaderName(beanField);
header[i] = columnHeaderName;
}
return header;
}
private String extractHeaderName(final BeanField beanField) {
if (beanField == null || beanField.getField() == null || beanField.getField().getDeclaredAnnotationsByType(
CsvBindByName.class).length == 0) {
return StringUtils.EMPTY;
}
final CsvBindByName bindByNameAnnotation = beanField.getField().getDeclaredAnnotationsByType(CsvBindByName.class)[0];
return bindByNameAnnotation.column();
}
}
@CsvBindByName(column = "id")
@CsvBindByPosition(position = 0)
private Long id;
@CsvBindByName(column = "name")
@CsvBindByPosition(position = 1)
private String name;
public static <T extends AbstractCsv> String createCsv(List<T> data, Class<T> beanClazz) {
CustomMappingStrategy<T> mappingStrategy = new CustomMappingStrategy<T>();
mappingStrategy.setType(beanClazz);
StringWriter writer = new StringWriter();
String csv = "";
try {
StatefulBeanToCsv sbc = new StatefulBeanToCsvBuilder(writer)
.withSeparator(';')
.withMappingStrategy(mappingStrategy)
.build();
sbc.write(data);
csv = writer.toString();
} catch (CsvRequiredFieldEmptyException e) {
// TODO add some logging...
} catch (CsvDataTypeMismatchException e) {
// TODO add some logging...
} finally {
try {
writer.close();
} catch (IOException e) {
}
}
return csv;
}
HeaderColumnNameMappingStrategy<MyCsvBean> mappingStrategy = new HeaderColumnNameMappingStrategy<>();
mappingStrategy.setType(MyCsvBean.class);
mappingStrategy.setColumnOrderOnWrite(new ClassFieldOrderComparator(MyCsvBean.class));
private class ClassFieldOrderComparator implements Comparator<String> {
List<String> fieldNamesInOrderWithinClass;
public ClassFieldOrderComparator(Class<?> clazz) {
fieldNamesInOrderWithinClass = Arrays.stream(clazz.getDeclaredFields())
.filter(field -> field.getAnnotation(CsvBindByName.class) != null)
// Handle order by your custom annotation here
//.sorted((field1, field2) -> {
// int field1Order = field1.getAnnotation(YourCustomOrderAnnotation.class).getOrder();
// int field2Order = field2.getAnnotation(YourCustomOrderAnnotation.class).getOrder();
// return Integer.compare(field1Order, field2Order);
//})
.map(field -> field.getName().toUpperCase())
.collect(Collectors.toList());
}
@Override
public int compare(String o1, String o2) {
int fieldIndexo1 = fieldNamesInOrderWithinClass.indexOf(o1);
int fieldIndexo2 = fieldNamesInOrderWithinClass.indexOf(o2);
return Integer.compare(fieldIndexo1, fieldIndexo2);
}
}
String[] csvHeader= {"Id#","Shiv Record Number","Shiv Vendor Id","Shiva Tech Id#","finShortNameTb","finVenName1Tb","finVenName2Tb"};
CustomMappingStrategy<FinVendor> mappingStrategy = new CustomMappingStrategy(csvHeader);//csvHeader as per custom header irrespective of pojo field name
mappingStrategy.setType(FinVendor.class);
mappingStrategy.setColumnMapping(fields);//pojo mapping fields
StatefulBeanToCsv<FinVendor> beanToCsv = new StatefulBeanToCsvBuilder<FinVendor>(writer).withQuotechar(CSVWriter.NO_QUOTE_CHARACTER).withMappingStrategy(mappingStrategy).build();
beanToCsv.write(readVendors);
String[] header;
public CustomMappingStrategy(String[] cols) {
header = cols;
}
@Override
public String[] generateHeader(T bean) throws CsvRequiredFieldEmptyException {
super.generateHeader(bean);
return header;
}
}
Id# Shiv Record Number Shiv Vendor Id Fin Tech Id# finShortNameTb finVenName1Tb finVenName2Tb finVenDefaultLocTb
1 VEN00053 678 33316025986 THE ssOHIO S_2 THE UNIVERSITY CHK Test
2 VEN02277 1217 3044374205 Fe3 MECHA_1 FR3INC EFT-1
3 VEN03118 1310 30234484121 PE333PECTUS_1 PER332CTUS AR EFT-1 Test
import com.opencsv.bean.BeanField;
import com.opencsv.bean.ColumnPositionMappingStrategy;
import com.opencsv.bean.CsvBindByName;
import com.opencsv.exceptions.CsvRequiredFieldEmptyException;
/**
* @param <T>
*/
class CustomMappingStrategy<T> extends ColumnPositionMappingStrategy<T> {
/*
* (non-Javadoc)
*
* @see com.opencsv.bean.ColumnPositionMappingStrategy#generateHeader(java.lang.
* Object)
*/
@Override
public String[] generateHeader(T bean) throws CsvRequiredFieldEmptyException {
final int numColumns = getFieldMap().values().size();
if (numColumns == -1) {
return super.generateHeader(bean);
}
String[] header = new String[numColumns];
super.setColumnMapping(header);
BeanField<T, Integer> beanField;
for (int i = 0; i < numColumns; i++) {
beanField = findField(i);
String columnHeaderName = beanField.getField().getDeclaredAnnotation(CsvBindByName.class).column();
header[i] = columnHeaderName;
}
return header;
}
}
CustomMappingStrategy<ScanReport> strategy = new CustomMappingStrategy<>();
strategy.setType(ScanReport.class);
// Write a bean to csv file.
StatefulBeanToCsv<ScanReport> beanToCsv = new StatefulBeanToCsvBuilder<ScanReport>(writer)
.withMappingStrategy(strategy).build();
beanToCsv.write(beanList);
public class CustomBeanToCSVMappingStrategy<T> extends ColumnPositionMappingStrategy<T> {
@Override
public String[] generateHeader(T bean) throws CsvRequiredFieldEmptyException {
String[] headersAsPerFieldName = getFieldMap().generateHeader(bean); // header name based on field name
String[] header = new String[headersAsPerFieldName.length];
for (int i = 0; i <= headersAsPerFieldName.length - 1; i++) {
BeanField beanField = findField(i);
String columnHeaderName = extractHeaderName(beanField); // header name based on @CsvBindByName annotation
if (columnHeaderName.isEmpty()) // No @CsvBindByName is present
columnHeaderName = headersAsPerFieldName[i]; // defaults to header name based on field name
header[i] = columnHeaderName;
}
headerIndex.initializeHeaderIndex(header);
return header;
}
private String extractHeaderName(final BeanField beanField) {
if (beanField == null || beanField.getField() == null || beanField.getField().getDeclaredAnnotationsByType(CsvBindByName.class).length == 0) {
return StringUtils.EMPTY;
}
final CsvBindByName bindByNameAnnotation = beanField.getField().getDeclaredAnnotationsByType(CsvBindByName.class)[0];
return bindByNameAnnotation.column();
}
}
@Getter @Setter @ToString
public class Pojo {
@CsvBindByName(column="Voucher Series") // header: "Voucher Series"
@CsvBindByPosition(position=0)
private String voucherSeries;
@CsvBindByPosition(position=1) // header: "salePurchaseType"
private String salePurchaseType;
}
CustomBeanToCSVMappingStrategy<Pojo> mappingStrategy = new CustomBeanToCSVMappingStrategy<>();
mappingStrategy.setType(Pojo.class);
StatefulBeanToCsv<Pojo> beanToCsv = new StatefulBeanToCsvBuilder<Pojo>(writer)
.withSeparator(CSVWriter.DEFAULT_SEPARATOR)
.withMappingStrategy(mappingStrategy)
.build();
beanToCsv.write(pojoList);
class CustomMappingStrategy<T> extends ColumnPositionMappingStrategy<T> {
private static final String[] HEADER = new String[]{"TradeID", "GWML GUID", "MXML GUID", "GWML File", "MxML File", "MxML Counterparty", "GWML Counterparty"};
@Override
public String[] generateHeader() {
super.generateHeader(bean); // without this the file contains ONLY headers
return HEADER;
}
@Target(ElementType.FIELD)
@Inherited
@Retention(RetentionPolicy.RUNTIME)
public @interface CsvPosition {
int position();
}
public class CustomMappingStrategy<T> extends HeaderColumnNameMappingStrategy<T> {
private final Field[] fields;
public CustomMappingStrategy(Class<T> clazz) {
fields = clazz.getDeclaredFields();
Arrays.sort(fields, (f1, f2) -> {
CsvPosition position1 = f1.getAnnotation(CsvPosition.class);
CsvPosition position2 = f2.getAnnotation(CsvPosition.class);
return Integer.compare(position1.position(), position2.position());
});
}
@Override
public String[] generateHeader(T bean) throws CsvRequiredFieldEmptyException {
String[] header = new String[fields.length];
for (Field f : fields) {
CsvPosition position = f.getAnnotation(CsvPosition.class);
header[position.position() - 1] = getName(f);
}
headerIndex.initializeHeaderIndex(header);
return header;
}
private String getName(Field f) {
CsvBindByName csvBindByName = f.getAnnotation(CsvBindByName.class);
CsvCustomBindByName csvCustomBindByName = f.getAnnotation(CsvCustomBindByName.class);
return csvCustomBindByName != null
? csvCustomBindByName.column() == null || csvCustomBindByName.column().isEmpty() ? f.getName() : csvCustomBindByName.column()
: csvBindByName.column() == null || csvBindByName.column().isEmpty() ? f.getName() : csvBindByName.column();
}
}
CustomMappingStrategy<Record> mappingStrategy = new CustomMappingStrategy<>(Record.class);
mappingStrategy.setType(Record.class);
StatefulBeanToCsv beanToCsv = new StatefulBeanToCsvBuilder(writer)
.withApplyQuotesToAll(false)
.withOrderedResults(true)
.withMappingStrategy(mappingStrategy)
.build();