java 带有列标题的 StatefulBeanToCsv
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/46072947/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
StatefulBeanToCsv with Column headers
提问by Bishan
I am using opencsv-4.0
to write a csv file and I need to add column headers in output file.
我正在opencsv-4.0
编写一个 csv 文件,我需要在输出文件中添加列标题。
Here is my code.
这是我的代码。
public static void buildProductCsv(final List<Product> product,
final String filePath) {
try {
Writer writer = new FileWriter(filePath);
// mapping of columns with their positions
ColumnPositionMappingStrategy<Product> mappingStrategy = new ColumnPositionMappingStrategy<Product>();
// Set mappingStrategy type to Product Type
mappingStrategy.setType(Product.class);
// Fields in Product Bean
String[] columns = new String[] { "productCode", "MFD", "EXD" };
// Setting the colums for mappingStrategy
mappingStrategy.setColumnMapping(columns);
StatefulBeanToCsvBuilder<Product> builder = new StatefulBeanToCsvBuilder<Product>(writer);
StatefulBeanToCsv<Product> beanWriter = builder.withMappingStrategy(mappingStrategy).build();
// Writing data to csv file
beanWriter.write(product);
writer.close();
log.info("Your csv file has been generated!");
} catch (Exception ex) {
log.warning("Exception: " + ex.getMessage());
}
}
Above code create a csv file with data. But it not include column headers in that file.
上面的代码创建一个包含数据的 csv 文件。但它不包括该文件中的列标题。
How could I add column headers to output csv?
如何将列标题添加到输出 csv?
回答by Jim West
ColumnPositionMappingStrategy#generateHeader returns empty array
ColumnPositionMappingStrategy#generateHeader 返回空数组
/**
* This method returns an empty array.
* The column position mapping strategy assumes that there is no header, and
* thus it also does not write one, accordingly.
* @return An empty array
*/
@Override
public String[] generateHeader() {
return new String[0];
}
If you remove MappingStrategy from BeanToCsv builder
如果您从 BeanToCsv 构建器中删除 MappingStrategy
// replace
StatefulBeanToCsv<Product> beanWriter = builder.withMappingStrategy(mappingStrategy).build();
// with
StatefulBeanToCsv<Product> beanWriter = builder.build();
It will write Product's class members as CSV header
它将产品的类成员写为 CSV 标头
If your Product class members names are
如果您的 Product 类成员名称是
"productCode", "MFD", "EXD"
This should be the right solution
这应该是正确的解决方案
Else, add @CsvBindByName annotation
否则,添加@CsvBindByName 注释
import com.opencsv.bean.CsvBindByName;
import com.opencsv.bean.StatefulBeanToCsv;
import com.opencsv.bean.StatefulBeanToCsvBuilder;
import java.io.FileWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;
public class CsvTest {
public static void main(String[] args) throws Exception {
Writer writer = new FileWriter(fileName);
StatefulBeanToCsvBuilder<Product> builder = new StatefulBeanToCsvBuilder<>(writer);
StatefulBeanToCsv<Product> beanWriter = builder.build();
List<Product> products = new ArrayList<>();
products.add(new Product("1", "11", "111"));
products.add(new Product("2", "22", "222"));
products.add(new Product("3", "33", "333"));
beanWriter.write(products);
writer.close();
}
public static class Product {
@CsvBindByName(column = "productCode")
String id;
@CsvBindByName(column = "MFD")
String member2;
@CsvBindByName(column = "EXD")
String member3;
Product(String id, String member2, String member3) {
this.id = id;
this.member2 = member2;
this.member3 = member3;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getMember2() {
return member2;
}
public void setMember2(String member2) {
this.member2 = member2;
}
public String getMember3() {
return member3;
}
public void setMember3(String member3) {
this.member3 = member3;
}
}
}
Output:
输出:
"EXD","MFD","PRODUCTCODE"
"111","11","1"
"222","22","2"
"333","33","3"
“EXD”、“MFD”、“产品代码”
“111”、“11”、“1”
“222”、“22”、“2”
“333”、“33”、“3”
Pay attention; class, getters & setters needs to be public due to the use of Reflection by OpenCSV library
注意; 由于 OpenCSV 库使用反射,类、getter 和 setter 需要公开
回答by Ithar
I may have missed something obvious here but couldn't you just append your header String to the writer object?
我可能在这里遗漏了一些明显的内容,但您不能将标题字符串附加到 writer 对象吗?
Writer writer = new FileWriter(filePath);
writer.append("header1, header2, header3, ...etc \n");
// This will be followed by your code with BeanToCsvBuilder
// Note: the terminating \n might differ pending env.
回答by Bruno Muehlbauer de Souza
You can append by annotation
您可以通过注释追加
public void export(List<YourObject> list, PrintWriter writer) throws Exception {
writer.append( buildHeader( YourObject.class ) );
StatefulBeanToCsvBuilder<YourObject> builder = new StatefulBeanToCsvBuilder<>( writer );
StatefulBeanToCsv<YourObject> beanWriter = builder.build();
beanWriter.write( mapper.map( list ) );
writer.close();
}
private String buildHeader(Class<YourObject> clazz) {
return Arrays.stream( clazz.getDeclaredFields() )
.filter( f -> f.getAnnotation( CsvBindByPosition.class ) != null
&& f.getAnnotation( CsvBindByName.class ) != null )
.sorted( Comparator.comparing( f -> f.getAnnotation( CsvBindByPosition.class ).position() ) )
.map( f -> f.getAnnotation( CsvBindByName.class ).column() )
.collect( Collectors.joining( "," ) ) + "\n";
}
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class YourObject {
@CsvBindByPosition(position = 0)
@CsvBindByName(column = "A")
private Long a;
@CsvBindByPosition(position = 1)
@CsvBindByName(column = "B")
private String b;
@CsvBindByPosition(position = 2)
@CsvBindByName(column = "C")
private String c;
}
回答by fcecchin
Not so good, but the easiest way is just appending a header to writer object ...
不太好,但最简单的方法是将标头附加到 writer 对象...
...
ByteArrayOutputStream os = new ByteArrayOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
osw.append("PRODUCTCODE;EXD;MFD\n");
CSVWriter writer = new CSVWriter(osw, ';', CSVWriter.NO_QUOTE_CHARACTER, CSVWriter.DEFAULT_ESCAPE_CHARACTER,
CSVWriter.DEFAULT_LINE_END);
StatefulBeanToCsv<Product> beanToCsv = new StatefulBeanToCsvBuilder<Product>(writer)
.build();
beanToCsv.write(linhas);