BeanIO核心概念
BeanReader 从inputstream中读取对象
read()返回记录,直到下一个记录为空
getRecordName(),返回xml中record名字
getLineNumber() returns the line number of the first record mapped to the most recent bean object read from the input stream
close() ,使用完成后需要关闭输入流
BeanWriter 将对象写入到outputstream
Unmarshaller 解码器,从字符串中解析出java bean对象
Marshaller 编码器,将一个java bean对象编码成字符串
将一个java bean输出成String的简写方法如下
String recordText = marshaller.marshal(object).toString();
Mapping Files 映射文件(object到stream)
StreamFactory 加载映射文件,创建BeanReader、BeanWriter、Unmarshaller、Marshaller。
加载文件,创建BeanReader、BeanWriter、Unmarshaller、Marshalle请参考示例代码
Exception Handling 异常处理
BeanIO的所有异常扩展自BeanIOException,BeanIOException继承自RuntimeException
BeanReaderErrorHandler 读取错误处理器
如果读取错误,但仍想继续处理结果,需要注册一个错误处理器
Stream Components 流组件
不管使用builder API、映射文件、java 注解,或者以上组合,相关概念都相同。
Streams
必须要有两个属性,name和format。name为stream的唯一标识,format表示解析的是xml,、csv,、delimited、fixedlength类型。
可以使用parser元素制定解析方法。
<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="s1" format="delmiited">
<parser>
<property name="delimiter" value="|" />
</parser>
<!-- record layout... -->
</stream>
</beanio>
CSV Streams
Parser的定义方法。。。
Delimited Streams
Parser的定义方法。。。
Fixed Length Streams
Parser的定义方法,属性
lineContinuationCharacter 换行连接符,默认关闭。如果设置了,表示一下行也是上一行的连续。
recordTerminator 记录终结符,表示一条记录的完结,默认是LF、CR或者CRLF。
comments 记录注释符,输入多个注释符,用逗号分隔,如果记录开头为记录注释符,该行会被认为是注释被忽略。
XML Streams
Parser的定义方法。。。
Records
一个stream至少有一个record。举例如下
<beanio>
<stream name="stream1" format="csv">
<record name="record1" class="example.Record">
<field name="firstName" />
<field name="lastName" />
<field name="age" />
</record>
</stream>
</beanio>
可以在field元素中设置类型,例如
<stream name="stream1" format="csv">
<record name="record1" class="map">
<field name="firstName" />
<field name="lastName" />
<field name="age" type="int"/>
</record>
</stream>
Record Identification
一个文件可能包含多个record部分,比如title、body、tailer,下面例子就有header、detail、trailer三个record部分。
Header,01012011
Detail,Joe,Smith,Developer,75000,10012009
Detail,Jane,Doe,Architect,80000,01152008
Detail,Jon,Anderson,Manager,85000,03182007
Trailer,3
<beanio>
<stream name="employeeFile" format="csv">
<record name="header" minOccurs="1" maxOccurs="1" class="example.Header">
<field name="recordType" rid="true" literal="Header" />
<field name="fileDate" format="MMddyyyy" />
</record>
<record name="employee" minOccurs="0" maxOccurs="unbounded" class="example.Employee">
<field name="recordType" rid="true" literal="Detail" />
<field name="firstName" />
<field name="lastName" />
<field name="title" />
<field name="salary" />
<field name="hireDate" format="MMddyyyy" />
</record>
<record name="trailer" minOccurs="1" maxOccurs="1" class="example.Trailer">
<field name="recordType" rid="true" literal="Trailer" />
<field name="recordCount" />
</record>
</stream>
</beanio>
rid="true"表示该字段是用来区别每一个record的
literal="Header"是区别record的匹配规则
minOccurs="1" maxOccurs="1"表示出现record次数,不设置默认为0和unbounded
Record Ordering
<record name="header" order="1" minOccurs="1" maxOccurs="1" class="example.Header">
order表示record顺序
Record Grouping
Record可以分组出现,具体看例子
Header,01012011
DeptHeader,Development
Detail,Joe,Smith,Developer,75000,10012009
Detail,Jane,Doe,Architect,80000,01152008
DeptTrailer,2
DeptHeader,Product Management
Detail,Jon,Anderson,Manager,85000,03182007
DeptTrailer,1
Trailer,2
<beanio>
<stream name="employeeFile" format="csv">
<record name="header" order="1" minOccurs="1" maxOccurs="1" class="example.Header">
<field name="recordType" rid="true" literal="Header" />
<field name="fileDate" format="MMddyyyy" />
</record>
<group name="departmentGroup" order="2" minOccurs="0" maxOccurs"unbounded">
<record name="deptHeader" order="1" minOccurs="1" maxOccurs="1" class="example.DeptHeader">
<field name="recordType" rid="true" literal="DeptHeader" />
<field name="departmentName" />
</record>
<record name="employee" order="2" minOccurs="0" maxOccurs="unbounded" class="example.Employee">
<field name="recordType" rid="true" literal="Detail" />
<field name="firstName" />
<field name="lastName" />
<field name="title" />
<field name="salary" />
<field name="hireDate" format="MMddyyyy" />
</record>
<record name="deptTrailer" order="3" minOccurs="1" maxOccurs="1" class="example.DeptTrailer">
<field name="recordType" rid="true" literal="DeptTrailer" />
<field name="employeeCount" />
</record>
</group>
<record name="trailer" order="3" minOccurs="1" maxOccurs="1" class="example.Trailer">
<field name="recordType" rid="true" literal="Trailer" />
<field name="departmentCount" />
</record>
</stream>
</beanio>
Fields
setter="setSurname" getter="getSurname" 表示设置不同的setter,getter方法
ignore="true" 表示忽略该字段
position="3"表示字段顺序,从0开始,不设置则以默认声明顺序为准
Field Type Conversion 字段类型转换
默认转换成String,可以使用type显式设置转换类型
format可以作为字段格式化
<field name="hireDate" type="date" format="yyyy-MM-dd" />
Custom Type Handlers 自定义类型转换处理器
Repeating Fields
重复字段,比如
Joe,Smith,Developer,75000,10012009
Chris,Johnson,Sales,80000,05292006,100012,200034,200045
Jane,Doe,Architect,80000,01152008
Jon,Anderson,Manager,85000,03182007,333001
public class Employee {
String firstName;
String lastName;
String title;
int salary;
Date hireDate;
List<Integer> accounts;
// getters and setters not shown...
}
账号100012,200034,200045全部放到List<Integer> accounts中。支持设置最大最小重复次数
Fixed Length Fields
定长字段有特殊设置,例如
Joe Smith Developer 07500010012009
Jane Doe Architect 08000001152008
Jon Anderson Manager 08500003182007
<beanio>
<stream name="employeeFile" format="csv">
<record name="employee" class="example.Employee">
<field name="firstName" length="10" />
<field name="lastName" length="10" />
<field name="title" length="10" />
<field name="salary" length="6" padding="0" justify="right" />
<field name="hireDate" length="8" format="MMddyyyy" />
</record>
</stream>
</beanio>
。。。。省略
Stream Validation 校验
如果校验不通过,将抛出InvalidRecordException
可以注册一个handler处理exception,这样就可以出错是继续处理。
Record Validation
最长最短校验
Field Validation
必须,最小最大长度,文字严格匹配,正则,最少出现次数
Templates 字段模板
配合position的时候可以设置offset
。。。。省略
Annotations and the Stream Builder API 注解
Builder方式
Annotation方式
强烈推荐使用at属性制定字段,无法保证顺序