想从 beanIO 字段名称标签在 csv 中写入 header
want to write header in csv from beanIO field name tag
我想在 csv 文件中写一个 header 因为我的文本文件不包含任何 header 所以我想从 beanIO 字段名称标签写它
我有一个带有两个流的 beanIO,一个用于读取,另一个用于写入
这是输入文件....
textInput.txt-
1 约翰露 BA xxx
1sam hart MA yyy
public static void main(String[] args) throws Exception {
StreamFactory factory = StreamFactory.newInstance();
factory.load("C:\Users\PV5057094\Demo_workspace\XlsxMapper\src\main\resources\Employee.xml");
BeanReader br = factory.createReader("EmployeeInfo",new File("C:\Temp\Soc\textInput.txt"));
BeanWriter out = factory.createWriter("EmployeeInfoCSV", new File("C:\Temp\Soc\output.csv"));
Object record;
while ((record=br.read())!=null) {
out.write(record);
System.out.println("Record Written:" + record.toString());
}
// in.close();
out.flush();
out.close();
}
}
BeanIO-
<?xml version="1.0" encoding="UTF-8"?>
<beanio xmlns="http://www.beanio.org/2012/03"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.beanio.org/2012/03 http://www.beanio.org/2012/03/mapping.xsd">
<stream name="EmployeeInfo" format="fixedlength">
<record name="a" minOccurs="0" maxOccurs="unbounded"
class="com.aexp.gmnt.imc.record.submission.Employee">
<field name="record" length="1" literal="1" rid="true"/>
<field name="firstName" length="5"/>
<field name="lastName" length="5"/>
<field name="title" length="5"/>
<field name="filler" length="5"/>
</record>
</stream>
<stream name="EmployeeInfoCSV" format="csv">
<record name="a" minOccurs="0" maxOccurs="unbounded"
class="com.aexp.gmnt.imc.record.submission.Employee">
<field name="record" length="1" literal="1" rid="true"/>
<field name="firstName" length="5"/>
<field name="lastName" length="5"/>
<field name="title" length="5"/>
<field name="filler" length="5"/>
</record>
</stream>
</beanio>
预期输出-
记录、名字、姓氏、职务、填充人
1,john,dew,BA,xxx
1,sam,hart,MA,yyy
您必须在 EmployeeInfoCSV
流定义中定义一个新的 record
,它将包含列名作为该字段的默认值,例如
<record name="headers" minOccurs="1" maxOccurs="1">
<field name="recordColumn" default="Record"/>
然后你必须告诉你的BeanWriter
先写出一条"headers"的记录,然后再输出文件的其余部分。
out.write("headers", null);
您还必须将 CSV 流中 a
记录的 length
属性更改为 maxLength
,否则您将在输出中填充内容,但它看起来仍然像一个固定长度的格式。
改变
<field name="firstName" length="5"/>
到
<field name="firstName" maxLength="5"/>
然后把这些放在一起:
public static void main(String[] args) throws Exception {
StreamFactory factory = StreamFactory.newInstance();
factory.load("C:\Users\PV5057094\Demo_workspace\XlsxMapper\src\main\resources\Employee.xml");
BeanReader br = factory.createReader("EmployeeInfo",new File("C:\Temp\Soc\textInput.txt"));
BeanWriter out = factory.createWriter("EmployeeInfoCSV", new File("C:\Temp\Soc\output.csv"));
// write the column headers to the output file
out.write("headers", null);
Object record;
while ((record=br.read())!=null) {
out.write(record);
System.out.println("Record Written:" + record.toString());
}
br.close(); // yes, also close the reader
out.flush();
out.close();
}
和映射文件:
<?xml version="1.0" encoding="UTF-8"?>
<beanio xmlns="http://www.beanio.org/2012/03"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.beanio.org/2012/03 http://www.beanio.org/2012/03/mapping.xsd">
<stream name="EmployeeInfo" format="fixedlength">
<record name="a" minOccurs="0" maxOccurs="unbounded"
class="com.aexp.gmnt.imc.record.submission.Employee">
<field name="record" length="1" literal="1" rid="true"/>
<field name="firstName" length="5"/>
<field name="lastName" length="5"/>
<field name="title" length="5"/>
<field name="filler" length="5"/>
</record>
</stream>
<stream name="EmployeeInfoCSV" format="csv">
<record name="headers" minOccurs="1" maxOccurs="1">
<field name="recordColumn" default="Record"/>
<field name="firstNameColumn" default="FirstName"/>
<field name="lastNameColumn" default="LastName"/>
<field name="titleColumn" default="Title"/>
<field name="fillerColumn" default="Filler"/>
</record>
<record name="a" minOccurs="0" maxOccurs="unbounded"
class="com.aexp.gmnt.imc.record.submission.Employee">
<field name="record" length="1"/>
<field name="firstName" maxLength="5"/>
<field name="lastName" maxLength="5"/>
<field name="title" maxLength="5"/>
<field name="filler" maxLength="5"/>
</record>
</stream>
</beanio>
我已经编写了一个实用程序方法来根据原始记录中设置的 @Field.name
属性动态创建 Header 记录,它可能被认为是 hack,但它比创建新记录更好class 或创建一个 XML 文件只是为了打印 CSV header 行 IMO。
import java.io.ByteArrayOutputStream;
import java.io.OutputStreamWriter;
import org.beanio.BeanWriter;
import org.beanio.StreamFactory;
import org.beanio.annotation.Field;
import org.beanio.annotation.Record;
import org.beanio.builder.FieldBuilder;
import org.beanio.builder.RecordBuilder;
import org.beanio.builder.StreamBuilder;
public class Headers {
public static void main(String[] args) {
final String factoryName = "comma delimited csv factory";
final String headerName = "CarHeader";
final var builder = new StreamBuilder(factoryName)
.format("csv")
.addRecord(Headers.of(Car.class, headerName))
.addRecord(Car.class)
;
final var factory = StreamFactory.newInstance();
factory.define(builder);
final ByteArrayOutputStream bout = new ByteArrayOutputStream();
final BeanWriter writer = factory.createWriter(factoryName, new OutputStreamWriter(bout));
try {
writer.write(headerName, null);
writer.write(new Car("Ford Ka", 2016));
writer.write(new Car("Ford Fusion", 2020));
} finally {
writer.close();
}
System.out.println(bout.toString());
// Model,Year
// Ford Ka,2016
// Ford Fusion,2020
}
public static RecordBuilder of(Class<?> clazz, String name) {
final RecordBuilder builder = new RecordBuilder(name)
.order(1);
if (clazz.getAnnotation(Record.class) == null) {
throw new IllegalArgumentException("Class must be a BeanIo Record, annotated with @Record");
}
for (java.lang.reflect.Field classField : clazz.getDeclaredFields()) {
final Field fieldAnnotation = classField.getAnnotation(Field.class);
if (fieldAnnotation == null) {
continue;
}
builder.addField(
new FieldBuilder(fieldAnnotation.name())
.defaultValue(fieldAnnotation.name())
);
}
return builder;
}
@Record(order = 2)
static class Car {
@Field(name = "Model")
private String model;
@Field(name = "Year")
private Integer year;
public Car(String model, Integer year) {
this.model = model;
this.year = year;
}
public String getModel() {
return model;
}
public Integer getYear() {
return year;
}
public Car setModel(String model) {
this.model = model;
return this;
}
public Car setYear(Integer year) {
this.year = year;
return this;
}
}
}
我想在 csv 文件中写一个 header 因为我的文本文件不包含任何 header 所以我想从 beanIO 字段名称标签写它
我有一个带有两个流的 beanIO,一个用于读取,另一个用于写入
这是输入文件....
textInput.txt-
1 约翰露 BA xxx
1sam hart MA yyy
public static void main(String[] args) throws Exception {
StreamFactory factory = StreamFactory.newInstance();
factory.load("C:\Users\PV5057094\Demo_workspace\XlsxMapper\src\main\resources\Employee.xml");
BeanReader br = factory.createReader("EmployeeInfo",new File("C:\Temp\Soc\textInput.txt"));
BeanWriter out = factory.createWriter("EmployeeInfoCSV", new File("C:\Temp\Soc\output.csv"));
Object record;
while ((record=br.read())!=null) {
out.write(record);
System.out.println("Record Written:" + record.toString());
}
// in.close();
out.flush();
out.close();
}
}
BeanIO-
<?xml version="1.0" encoding="UTF-8"?>
<beanio xmlns="http://www.beanio.org/2012/03"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.beanio.org/2012/03 http://www.beanio.org/2012/03/mapping.xsd">
<stream name="EmployeeInfo" format="fixedlength">
<record name="a" minOccurs="0" maxOccurs="unbounded"
class="com.aexp.gmnt.imc.record.submission.Employee">
<field name="record" length="1" literal="1" rid="true"/>
<field name="firstName" length="5"/>
<field name="lastName" length="5"/>
<field name="title" length="5"/>
<field name="filler" length="5"/>
</record>
</stream>
<stream name="EmployeeInfoCSV" format="csv">
<record name="a" minOccurs="0" maxOccurs="unbounded"
class="com.aexp.gmnt.imc.record.submission.Employee">
<field name="record" length="1" literal="1" rid="true"/>
<field name="firstName" length="5"/>
<field name="lastName" length="5"/>
<field name="title" length="5"/>
<field name="filler" length="5"/>
</record>
</stream>
</beanio>
预期输出-
记录、名字、姓氏、职务、填充人
1,john,dew,BA,xxx
1,sam,hart,MA,yyy
您必须在 EmployeeInfoCSV
流定义中定义一个新的 record
,它将包含列名作为该字段的默认值,例如
<record name="headers" minOccurs="1" maxOccurs="1">
<field name="recordColumn" default="Record"/>
然后你必须告诉你的BeanWriter
先写出一条"headers"的记录,然后再输出文件的其余部分。
out.write("headers", null);
您还必须将 CSV 流中 a
记录的 length
属性更改为 maxLength
,否则您将在输出中填充内容,但它看起来仍然像一个固定长度的格式。
改变
<field name="firstName" length="5"/>
到
<field name="firstName" maxLength="5"/>
然后把这些放在一起:
public static void main(String[] args) throws Exception {
StreamFactory factory = StreamFactory.newInstance();
factory.load("C:\Users\PV5057094\Demo_workspace\XlsxMapper\src\main\resources\Employee.xml");
BeanReader br = factory.createReader("EmployeeInfo",new File("C:\Temp\Soc\textInput.txt"));
BeanWriter out = factory.createWriter("EmployeeInfoCSV", new File("C:\Temp\Soc\output.csv"));
// write the column headers to the output file
out.write("headers", null);
Object record;
while ((record=br.read())!=null) {
out.write(record);
System.out.println("Record Written:" + record.toString());
}
br.close(); // yes, also close the reader
out.flush();
out.close();
}
和映射文件:
<?xml version="1.0" encoding="UTF-8"?>
<beanio xmlns="http://www.beanio.org/2012/03"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.beanio.org/2012/03 http://www.beanio.org/2012/03/mapping.xsd">
<stream name="EmployeeInfo" format="fixedlength">
<record name="a" minOccurs="0" maxOccurs="unbounded"
class="com.aexp.gmnt.imc.record.submission.Employee">
<field name="record" length="1" literal="1" rid="true"/>
<field name="firstName" length="5"/>
<field name="lastName" length="5"/>
<field name="title" length="5"/>
<field name="filler" length="5"/>
</record>
</stream>
<stream name="EmployeeInfoCSV" format="csv">
<record name="headers" minOccurs="1" maxOccurs="1">
<field name="recordColumn" default="Record"/>
<field name="firstNameColumn" default="FirstName"/>
<field name="lastNameColumn" default="LastName"/>
<field name="titleColumn" default="Title"/>
<field name="fillerColumn" default="Filler"/>
</record>
<record name="a" minOccurs="0" maxOccurs="unbounded"
class="com.aexp.gmnt.imc.record.submission.Employee">
<field name="record" length="1"/>
<field name="firstName" maxLength="5"/>
<field name="lastName" maxLength="5"/>
<field name="title" maxLength="5"/>
<field name="filler" maxLength="5"/>
</record>
</stream>
</beanio>
我已经编写了一个实用程序方法来根据原始记录中设置的 @Field.name
属性动态创建 Header 记录,它可能被认为是 hack,但它比创建新记录更好class 或创建一个 XML 文件只是为了打印 CSV header 行 IMO。
import java.io.ByteArrayOutputStream;
import java.io.OutputStreamWriter;
import org.beanio.BeanWriter;
import org.beanio.StreamFactory;
import org.beanio.annotation.Field;
import org.beanio.annotation.Record;
import org.beanio.builder.FieldBuilder;
import org.beanio.builder.RecordBuilder;
import org.beanio.builder.StreamBuilder;
public class Headers {
public static void main(String[] args) {
final String factoryName = "comma delimited csv factory";
final String headerName = "CarHeader";
final var builder = new StreamBuilder(factoryName)
.format("csv")
.addRecord(Headers.of(Car.class, headerName))
.addRecord(Car.class)
;
final var factory = StreamFactory.newInstance();
factory.define(builder);
final ByteArrayOutputStream bout = new ByteArrayOutputStream();
final BeanWriter writer = factory.createWriter(factoryName, new OutputStreamWriter(bout));
try {
writer.write(headerName, null);
writer.write(new Car("Ford Ka", 2016));
writer.write(new Car("Ford Fusion", 2020));
} finally {
writer.close();
}
System.out.println(bout.toString());
// Model,Year
// Ford Ka,2016
// Ford Fusion,2020
}
public static RecordBuilder of(Class<?> clazz, String name) {
final RecordBuilder builder = new RecordBuilder(name)
.order(1);
if (clazz.getAnnotation(Record.class) == null) {
throw new IllegalArgumentException("Class must be a BeanIo Record, annotated with @Record");
}
for (java.lang.reflect.Field classField : clazz.getDeclaredFields()) {
final Field fieldAnnotation = classField.getAnnotation(Field.class);
if (fieldAnnotation == null) {
continue;
}
builder.addField(
new FieldBuilder(fieldAnnotation.name())
.defaultValue(fieldAnnotation.name())
);
}
return builder;
}
@Record(order = 2)
static class Car {
@Field(name = "Model")
private String model;
@Field(name = "Year")
private Integer year;
public Car(String model, Integer year) {
this.model = model;
this.year = year;
}
public String getModel() {
return model;
}
public Integer getYear() {
return year;
}
public Car setModel(String model) {
this.model = model;
return this;
}
public Car setYear(Integer year) {
this.year = year;
return this;
}
}
}