Java opencsv在集合的开始和结束处添加分隔符

Java opencsv在集合的开始和结束处添加分隔符,java,export-to-csv,opencsv,Java,Export To Csv,Opencsv,我试图通过opencsv导出一个bean,但在导出结构中遇到了一个小问题 我有几个这样的专栏 @CsvBindAndSplitByPosition(position = 16, splitOn = "\\|", converter = MultiAttributeValueConverter.class, elementType = MultiAttributeValue.class, writeDelimiter = "|") priva

我试图通过opencsv导出一个bean,但在导出结构中遇到了一个小问题

我有几个这样的专栏

    @CsvBindAndSplitByPosition(position = 16, splitOn = "\\|", converter = MultiAttributeValueConverter.class, elementType = MultiAttributeValue.class, writeDelimiter = "|")
    private List<MultiAttributeValue> attributes;
我需要稍微不同的输出

...,"|attribute1=value|attribute2=value2|attribute3=value3|",...
我需要对这些领域进行引导和跟踪。 目前,我不知道如何添加这些默认功能,也不知道在哪里添加

对任何输入或提示都很满意


在有关MultiVValue属性的注释信息中编辑为请求 目前无法访问代码,因此描述比较松散,尽管这不会影响我的案例,因为我对简单字符串也会有同样的问题

class MultivValueAttribute {
    String name;
    String value;
    ...
}

Converter:
    return name+value;

虽然不漂亮,但我确实找到了使用自定义绑定转换器的解决方案:

public class CustomBindingConverter<T, I> extends AbstractBeanField<T, I>
{
    private CustomFormatBeanFieldSplit<T, I> myConvert = null;

    @Override
    public void setField(Field field)
    {
        // TODO Auto-generated method stub
        super.setField(field);
        if (field.isAnnotationPresent(CsvBindAndSplitByPosition.class))
        {
            CsvBindAndSplitByPosition annotation = field.getAnnotation(CsvBindAndSplitByPosition.class);
            String fieldLocale = annotation.locale();
            String fieldWriteLocale = annotation.writeLocaleEqualsReadLocale() ? fieldLocale : annotation.writeLocale();
            Class<?> elementType = annotation.elementType();
            CsvConverter converter = determineConverter(field, elementType, fieldLocale, fieldWriteLocale,
                            annotation.converter());
            myConvert = new CustomFormatBeanFieldSplit<>(getType(), field, annotation.required(), errorLocale,
                            converter, annotation.splitOn(), annotation.writeDelimiter(), annotation.collectionType(),
                            annotation.elementType(), annotation.capture(), annotation.format());
        }
    }

    @Override
    protected Object convert(String value) throws CsvDataTypeMismatchException, CsvConstraintViolationException
    {
        return myConvert.convert(value);
    }

    @Override
    protected String convertToWrite(Object value) throws CsvDataTypeMismatchException, CsvRequiredFieldEmptyException
    {
        // TODO Auto-generated method stub
        return myConvert.convertToWrite(value);
    }

    protected CsvConverter determineConverter(Field field, Class<?> elementType, String locale, String writeLocale,
                    Class<? extends AbstractCsvConverter> customConverter) throws CsvBadConverterException
    {
        CsvConverter converter;

        // A custom converter always takes precedence if specified.
        if (customConverter != null && !customConverter.equals(AbstractCsvConverter.class))
        {
            try
            {
                converter = customConverter.newInstance();
            }
            catch(IllegalAccessException | InstantiationException oldEx)
            {
                CsvBadConverterException newEx = new CsvBadConverterException(customConverter,
                                String.format(ResourceBundle.getBundle(ICSVParser.DEFAULT_BUNDLE_NAME, errorLocale)
                                                .getString("custom.converter.invalid"),
                                                customConverter.getCanonicalName()));
                newEx.initCause(oldEx);
                throw newEx;
            }
            converter.setType(elementType);
            converter.setLocale(locale);
            converter.setWriteLocale(writeLocale);
            converter.setErrorLocale(errorLocale);
        }

        // Perhaps a date instead
        else if (field.isAnnotationPresent(CsvDate.class))
        {
            CsvDate annotation = field.getAnnotation(CsvDate.class);
            String readFormat = annotation.value();
            String writeFormat = annotation.writeFormatEqualsReadFormat() ? readFormat : annotation.writeFormat();
            String readChrono = annotation.chronology();
            String writeChrono = annotation.writeChronologyEqualsReadChronology() ? readChrono
                            : annotation.writeChronology();
            converter = new ConverterDate(elementType, locale, writeLocale, errorLocale, readFormat, writeFormat,
                            readChrono, writeChrono);
        }

        // Or a number
        else if (field.isAnnotationPresent(CsvNumber.class))
        {
            CsvNumber annotation = field.getAnnotation(CsvNumber.class);
            String readFormat = annotation.value();
            String writeFormat = annotation.writeFormatEqualsReadFormat() ? readFormat : annotation.writeFormat();
            converter = new ConverterNumber(elementType, locale, writeLocale, errorLocale, readFormat, writeFormat);
        }

        // or a Currency
        else if (elementType.equals(java.util.Currency.class))
        {
            converter = new ConverterCurrency(errorLocale);
        }

        // Or an enumeration
        else if (elementType.isEnum())
        {
            converter = new ConverterEnum(elementType, locale, writeLocale, errorLocale);
        }

        // Otherwise a primitive
        else
        {
            converter = new ConverterPrimitiveTypes(elementType, locale, writeLocale, errorLocale);
        }

        return converter;
    }
}
公共类CustomBindingConverter扩展AbstractBeanField
{
私有CustomFormatBeanFieldSplit myConvert=null;
@凌驾
公共无效设置字段(字段)
{
//TODO自动生成的方法存根
super.setField(字段);
if(字段isAnnotationPresent(CsvBindAndSplitByPosition.class))
{
CsvBindAndSplitByPosition annotation=field.getAnnotation(CsvBindAndSplitByPosition.class);
String fieldLocale=annotation.locale();
字符串fieldWriteLocale=annotation.writeLocaleEqualsReadLocale()?fieldLocale:annotation.writeLocale();
类elementType=annotation.elementType();
CsvConverter converter converter=determineConverter(字段、元素类型、字段区域设置、字段写入比例、,
converter());
myConvert=new CustomFormatBeanFieldSplit(getType(),字段,annotation.required(),errorLocale,
转换器,annotation.splitOn(),annotation.writeDelimiter(),annotation.collectionType(),
annotation.elementType()、annotation.capture()、annotation.format();
}
}
@凌驾
受保护对象转换(字符串值)引发CsvDataTypeMismatchException、CsvConstraintViolationException
{
返回myConvert.convert(值);
}
@凌驾
受保护的字符串ConvertWrite(对象值)引发CsvDataTypeMismatchException、CsvRequiredFieldEmptyException
{
//TODO自动生成的方法存根
返回myConvert.ConvertWrite(值);
}
受保护的CsvConverter determineConverter(字段字段、类elementType、字符串区域设置、字符串writeLocale、,
类类型、字段、布尔值必填项、区域设置errorLocale、,
CSV转换器、字符串拆分器、字符串写入限制器、,
类元素类型、字符串捕获、字符串格式)
{
super(类型、字段、必填项、errorLocale、转换器、splitOn、writeDelimiter、collectionType、elementType、capture、,
格式);
this.writeFormat=格式;
this.writeDelimiter=writeDelimiter;
}
@凌驾
受保护的字符串ConvertWrite(对象值)
抛出CsvDataTypeMismatchException{
String retval=StringUtils.EMPTY;
if(值!=null){
@SuppressWarnings(“未选中”)集合集合=(集合)值;
String[]convertedValue=新字符串[collection.size()];
int i=0;
用于(对象o:集合){
convertedValue[i]=转换器。convertToWrite(o);
if(StringUtils.isNotEmpty)(this.writeFormat)
&&StringUtils.isNotEmpty(convertedValue[i])){
convertedValue[i]=String.format(this.writeFormat,convertedValue[i]);
}
i++;
}
String coreValue=StringUtils.join(convertedValue,writeDelimiter);
if(StringUtils.isEmpty(coreValue)){
返回核心值;
}
retval=writeDelimiter+coreValue+writeDelimiter;
}
返回返回;
}
@凌驾
受保护对象转换(字符串值)引发CsvDataTypeMismatchException、CsvConstraintViolationException
{
//TODO自动生成的方法存根
返回super.convert(值);
}
}

虽然不太漂亮,但我确实找到了使用自定义绑定转换器的解决方案:

public class CustomBindingConverter<T, I> extends AbstractBeanField<T, I>
{
    private CustomFormatBeanFieldSplit<T, I> myConvert = null;

    @Override
    public void setField(Field field)
    {
        // TODO Auto-generated method stub
        super.setField(field);
        if (field.isAnnotationPresent(CsvBindAndSplitByPosition.class))
        {
            CsvBindAndSplitByPosition annotation = field.getAnnotation(CsvBindAndSplitByPosition.class);
            String fieldLocale = annotation.locale();
            String fieldWriteLocale = annotation.writeLocaleEqualsReadLocale() ? fieldLocale : annotation.writeLocale();
            Class<?> elementType = annotation.elementType();
            CsvConverter converter = determineConverter(field, elementType, fieldLocale, fieldWriteLocale,
                            annotation.converter());
            myConvert = new CustomFormatBeanFieldSplit<>(getType(), field, annotation.required(), errorLocale,
                            converter, annotation.splitOn(), annotation.writeDelimiter(), annotation.collectionType(),
                            annotation.elementType(), annotation.capture(), annotation.format());
        }
    }

    @Override
    protected Object convert(String value) throws CsvDataTypeMismatchException, CsvConstraintViolationException
    {
        return myConvert.convert(value);
    }

    @Override
    protected String convertToWrite(Object value) throws CsvDataTypeMismatchException, CsvRequiredFieldEmptyException
    {
        // TODO Auto-generated method stub
        return myConvert.convertToWrite(value);
    }

    protected CsvConverter determineConverter(Field field, Class<?> elementType, String locale, String writeLocale,
                    Class<? extends AbstractCsvConverter> customConverter) throws CsvBadConverterException
    {
        CsvConverter converter;

        // A custom converter always takes precedence if specified.
        if (customConverter != null && !customConverter.equals(AbstractCsvConverter.class))
        {
            try
            {
                converter = customConverter.newInstance();
            }
            catch(IllegalAccessException | InstantiationException oldEx)
            {
                CsvBadConverterException newEx = new CsvBadConverterException(customConverter,
                                String.format(ResourceBundle.getBundle(ICSVParser.DEFAULT_BUNDLE_NAME, errorLocale)
                                                .getString("custom.converter.invalid"),
                                                customConverter.getCanonicalName()));
                newEx.initCause(oldEx);
                throw newEx;
            }
            converter.setType(elementType);
            converter.setLocale(locale);
            converter.setWriteLocale(writeLocale);
            converter.setErrorLocale(errorLocale);
        }

        // Perhaps a date instead
        else if (field.isAnnotationPresent(CsvDate.class))
        {
            CsvDate annotation = field.getAnnotation(CsvDate.class);
            String readFormat = annotation.value();
            String writeFormat = annotation.writeFormatEqualsReadFormat() ? readFormat : annotation.writeFormat();
            String readChrono = annotation.chronology();
            String writeChrono = annotation.writeChronologyEqualsReadChronology() ? readChrono
                            : annotation.writeChronology();
            converter = new ConverterDate(elementType, locale, writeLocale, errorLocale, readFormat, writeFormat,
                            readChrono, writeChrono);
        }

        // Or a number
        else if (field.isAnnotationPresent(CsvNumber.class))
        {
            CsvNumber annotation = field.getAnnotation(CsvNumber.class);
            String readFormat = annotation.value();
            String writeFormat = annotation.writeFormatEqualsReadFormat() ? readFormat : annotation.writeFormat();
            converter = new ConverterNumber(elementType, locale, writeLocale, errorLocale, readFormat, writeFormat);
        }

        // or a Currency
        else if (elementType.equals(java.util.Currency.class))
        {
            converter = new ConverterCurrency(errorLocale);
        }

        // Or an enumeration
        else if (elementType.isEnum())
        {
            converter = new ConverterEnum(elementType, locale, writeLocale, errorLocale);
        }

        // Otherwise a primitive
        else
        {
            converter = new ConverterPrimitiveTypes(elementType, locale, writeLocale, errorLocale);
        }

        return converter;
    }
}
公共类CustomBindingConverter扩展AbstractBeanField
{
私有CustomFormatBeanFieldSplit myConvert=null;
@凌驾
公共无效设置字段(字段)
{
//TODO自动生成的方法存根
super.setField(字段);
if(字段isAnnotationPresent(CsvBindAndSplitByPosition.class))
{
CsvBindAndSplitByPosition annotation=field.getAnnotation(CsvBindAndSplitByPosition.class);
String fieldLocale=annotation.locale();
字符串fieldWriteLocale=annotation.writeLocaleEqualsReadLocale()?fieldLocale:annotation.writeLocale();
类elementType=annotation.elementType();
CsvConverter converter converter=determineConverter(字段、元素类型、字段区域设置、字段写入比例、,
converter());
myConvert=new CustomFormatBeanFieldSplit(getType(),字段,annotation.required(),errorLocale,
转换器,annotation.splitOn(),annotation.writeDelimiter(),annotation.collectionType(),
annotation.elementType()、annotation.capture()、annotation.format();
}
}
@凌驾
受保护对象转换(字符串值)引发CsvDataTypeMismatchException、CsvConstraintViolationException
{
返回myConvert.convert(值);
}
@凌驾
受保护的字符串ConvertWrite(对象值)引发CsvDataTypeMismatchException、CsvRequiredFieldEmptyException
{
//TODO自动生成的方法存根
返回myConvert.ConvertWrite(值);
}
受保护的CSV转换器确定转换器(字段fi
public class CustomFormatBeanFieldSplit<T, I> extends BeanFieldSplit<T, I>
{

    String writeFormat;
    String writeDelimiter;
    
    public CustomFormatBeanFieldSplit(Class<?> type, Field field, boolean required, Locale errorLocale,
                    CsvConverter converter, String splitOn, String writeDelimiter,
                    Class<? extends Collection> collectionType, Class<?> elementType, String capture, String format)
    {
        super(type, field, required, errorLocale, converter, splitOn, writeDelimiter, collectionType, elementType, capture,
                        format);
        
        this.writeFormat = format;
        this.writeDelimiter = writeDelimiter;
    }
    
    @Override
    protected String convertToWrite(Object value)
            throws CsvDataTypeMismatchException {
        String retval = StringUtils.EMPTY;
        if(value != null) {
            @SuppressWarnings("unchecked") Collection<Object> collection = (Collection<Object>) value;
            String[] convertedValue = new String[collection.size()];
            int i = 0;
            for(Object o : collection) {
                convertedValue[i] = converter.convertToWrite(o);
                if(StringUtils.isNotEmpty(this.writeFormat)
                        && StringUtils.isNotEmpty(convertedValue[i])) {
                    convertedValue[i] = String.format(this.writeFormat, convertedValue[i]);
                }
                i++;
            }
            String coreValue = StringUtils.join(convertedValue, writeDelimiter);
            
            if(StringUtils.isEmpty(coreValue)) {
                return coreValue;
            }
            
            retval = writeDelimiter + coreValue + writeDelimiter;
        }
        return retval;
    }

    
    @Override
    protected Object convert(String value) throws CsvDataTypeMismatchException, CsvConstraintViolationException
    {
        // TODO Auto-generated method stub
        return super.convert(value);
    }
}