使用 OpenCSV 4.6 将 Beans 写入 CSV 文件时,所有标头都更改为大写。尽管 bean 有@CsvBindByName注释,但它正在更改为大写。
Java Bean:
public class ProjectInfo implements Serializable {
@CsvBindByName(column = "ProjectName",required = true)
private String projectName;
@CsvBindByName(column = "ProjectCode",required = true)
private String projectCode;
@CsvBindByName(column = "Visibility",required = true)
private String visibility;
//setters and getters
}
主要方法
public static void main(String[] args) throws IOException {
Collection<Serializable> projectInfos = getProjectsInfo();
try(BufferedWriter writer = new BufferedWriter(new FileWriter("test.csv"))){
StatefulBeanToCsvBuilder builder = new StatefulBeanToCsvBuilder(writer);
StatefulBeanToCsv beanWriter = builder
.withSeparator(';')
.build();
try {
beanWriter.write(projectInfos.iterator());
writer.flush();
} catch (CsvDataTypeMismatchException | CsvRequiredFieldEmptyException e) {
throw new RuntimeException("Failed to download admin file");
}
}
}
预期成果:
"ProjectCode";"ProjectName";"Visibility"
"ANY";"Country DU";"1"
"STD";"Standard";"1"
"TST";"Test";"1"
"CMM";"CMMTest";"1"
直接结果:
"PROJECTCODE";"PROJECTNAME";"VISIBILITY"
"ANY";"Country DU";"1"
"STD";"Standard";"1"
"TST";"Test";"1"
"CMM";"CMMTest";"1"
我没有使用 ColumnMappingStrategy 的选项,因为我必须将此方法构建为通用解决方案。谁能建议我如何按原样编写标题?
发生这种情况是因为 HeaderColumnNameMappingStrategy 中的代码用于存储和检索字段名称。toUpperCase()
你可以改用 HeaderColumnNameTranslateMappingStrategy,并通过反射创建映射。
public class AnnotationStrategy extends HeaderColumnNameTranslateMappingStrategy
{
public AnnotationStrategy(Class<?> clazz)
{
Map<String,String> map=new HashMap<>();
//To prevent the column sorting
List<String> originalFieldOrder=new ArrayList<>();
for(Field field:clazz.getDeclaredFields())
{
CsvBindByName annotation = field.getAnnotation(CsvBindByName.class);
if(annotation!=null)
{
map.put(annotation.column(),annotation.column());
originalFieldOrder.add(annotation.column());
}
}
setType(clazz);
setColumnMapping(map);
//Order the columns as they were created
setColumnOrderOnWrite((a,b) -> Integer.compare(originalFieldOrder.indexOf(a), originalFieldOrder.indexOf(b)));
}
@Override
public String[] generateHeader(Object bean) throws CsvRequiredFieldEmptyException
{
String[] result=super.generateHeader(bean);
for(int i=0;i<result.length;i++)
{
result[i]=getColumnName(i);
}
return result;
}
}
并且,假设只有一类项目(并且始终至少有一个项目),则必须扩展 的创建:beanWriter
StatefulBeanToCsv beanWriter = builder.withSeparator(';')
.withMappingStrategy(new AnnotationStrategy(projectInfos.iterator().next().getClass()))
.build();
是否可以通过在字段级别使用批注进行指定?
看看这个解决方案,这是你的反问题。
在该解决方案中,他们知道要映射哪些标头,例如“COLUMN1”->“name”,但在这里我将动态获取标头,因此我无法创建映射。
如果字段名称与@CsvBindByName中的列名称不同,那么我们必须更改映射以获取键和值,两者都应该是 Annotation.column()。如果我们同时使用annotation.column()键和值,那么它将解决所有问题。非常感谢您的回答,这对我有很大帮助。
我使用了您的解决方案,它对我很有用,因为它以小写形式转换了标题,但它也按 ASC 顺序对我的标题进行了排序,我不想更改标题的顺序。你能帮我这个吗