OpenCSV: Как создать файл CSV из POJO с пользовательскими заголовками столбцов и пользовательскими позициями столбцов?

Вы не могли итерировать или хранить больше данных, чем длина вашего массива. В этом случае вы можете сделать так:

for (int i = 0; i <= name.length - 1; i++) {
    // ....
}

Или это:

for (int i = 0; i < name.length; i++) {
    // ...
}
25
задан sebast26 12 September 2017 в 23:54
поделиться

2 ответа

В последней версии больше не работает решение @Sebast26. Однако основное все еще очень хорошо. Вот рабочее решение с v5.0

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;
}
0
ответ дан 28 November 2019 в 01:41
поделиться

Я думаю, что намеченный и самый гибкий способ обработать порядок столбцов заголовка состоит в том, чтобы ввести компаратор HeaderColumnNameMappinStrategy.setColumnOrderOnWrite ().

Для меня самый интуитивный путь состоял в том, чтобы записать столбцы CSV в том же порядке, как они указаны в CsvBean, но можно также скорректировать Компаратор для использования собственные аннотации, где Вы указываете порядок. DonВґt забывают переименовывать класс Компаратора затем ;)

Интеграция:

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);
    }
}
0
ответ дан 28 November 2019 в 01:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: