javascript
全网最详细SpringBatch读(Reader)跨多行文件讲解
文章列表
- 讀記錄跨多行文件
- 1、讀跨多行文件job配置
- 2、讀跨多行文件reader
- 3、自定義FieldSetMapper
- 4、讀跨多行文件processor
- 5、讀跨多行文件writer
寫在前面:
我是「境里婆娑」。我還是從前那個少年,沒有一絲絲改變,時間只不過是考驗,種在心中信念絲毫未減,眼前這個少年,還是最初那張臉,面前再多艱險不退卻。
寫博客的目的就是分享給大家一起學習交流,如果您對 Java感興趣,可以關注我,我們一起學習。
前言:在工作中可能會遇到SpringBatch讀取的文件記錄跨多行或者文件中存在多種不同的記錄格式,不必擔心SpringBatch已經幫我們把接口都預留好了,只需要稍微改造就可以輕松實現。
讀記錄跨多行文件
當Flat文件格式非標準是,通過實現記錄分隔策略接口RecordSeparatorPolicy來實現非標準Flat格式文件。非標準Flat文件有多種情況,例如記錄跨多行、以特定的字符開頭、以特定的字符結尾。
下面講的例子是每兩行表示一條記錄:
412222,201,tom,2020-02-27 ,china 412453,203,tqm,2020-03-27 ,us 412222,205,tym,2020-05-27 ,jap默認的記錄分割策略SimpleRecordSeparatorPolicy或者DefaultRecordSeparatorPolicy已經不能處理此類文件。我們可以實現接口RecordSeparatorPolicy來自定義分割策略MulitiLineRecordSeparatorPolicy
讀記錄跨多行文件時,使用到的核心組件類圖如下:
在本類圖中除了MulitiLineRecordSeparatorPolicy和CommonFieldSetMapper是自定義實現的,其他組件都是SpringBatch自帶。
MulitiLineRecordSeparatorPolicy:負責從文件中確認一條完整記錄,在本實現中每讀到四個逗號分隔符,則認為是一條完整的記錄
/*** @author shuliangzhao* @date 2020/12/6 13:05*/ public class MulitiLineRecordSeparatorPolicy implements RecordSeparatorPolicy {private String delimiter = ",";private int count = 0;public int getCount() {return count;}public void setCount(int count) {this.count = count;}public String getDelimiter() {return delimiter;}public void setDelimiter(String delimiter) {this.delimiter = delimiter;}@Overridepublic boolean isEndOfRecord(String record) {return countDelimiter(record) == count;}private int countDelimiter(String record) {String temp = record;int index = -1;int count = 0;while ((index=temp.indexOf(",")) != -1) {temp = temp.substring(index +1);count++;}return count;}@Overridepublic String postProcess(String record) {return record;}@Overridepublic String preProcess(String record) {return record;} }delimiter :定義為讀的的分割符號
count:分隔符總數,給定的字符串包含的分隔符個數等于此值,則認為是一條完整的記錄。
1、讀跨多行文件job配置
讀跨多行文件job基于javabean配置如下
/*** 讀記錄跨多行文件* @author shuliangzhao* @date 2020/12/6 13:38*/ @Configuration @EnableBatchProcessing public class MulitiLineConfiguration {@Autowiredprivate JobBuilderFactory jobBuilderFactory;@Autowiredprivate StepBuilderFactory stepBuilderFactory;@Autowiredprivate PartitonMultiFileProcessor partitonMultiFileProcessor;@Autowiredprivate PartitionMultiFileWriter partitionMultiFileWriter;@Beanpublic Job mulitiLineJob() {return jobBuilderFactory.get("mulitiLineJob").start(mulitiLineStep()).build();}@Beanpublic Step mulitiLineStep() {return stepBuilderFactory.get("mulitiLineStep").<CreditBill,CreditBill>chunk(12).reader(mulitiLineRecordReader()).processor(partitonMultiFileProcessor).writer(partitionMultiFileWriter).build();}@Bean@StepScopepublic MulitiLineRecordReader mulitiLineRecordReader() {return new MulitiLineRecordReader(CreditBill.class);} }2、讀跨多行文件reader
MulitiLineRecordReader詳細如下
/*** @author shuliangzhao* @date 2020/12/6 13:09*/ public class MulitiLineRecordReader extends FlatFileItemReader {public MulitiLineRecordReader(Class clz) {setResource(CommonUtil.createResource("D:\\aplus\\muliti\\muliti.csv"));String[] names = CommonUtil.names(clz);DefaultLineMapper defaultLineMapper = new DefaultLineMapper();CommonFieldSetMapper commonFieldSetMapper = new CommonFieldSetMapper();commonFieldSetMapper.setTargetType(clz);defaultLineMapper.setFieldSetMapper(commonFieldSetMapper);DelimitedLineTokenizer delimitedLineTokenizer = new DelimitedLineTokenizer();delimitedLineTokenizer.setFieldSetFactory(new DefaultFieldSetFactory());delimitedLineTokenizer.setNames(names);delimitedLineTokenizer.setDelimiter(",");defaultLineMapper.setLineTokenizer(delimitedLineTokenizer);MulitiLineRecordSeparatorPolicy mulitiLineRecordSeparatorPolicy = new MulitiLineRecordSeparatorPolicy();mulitiLineRecordSeparatorPolicy.setCount(4);mulitiLineRecordSeparatorPolicy.setDelimiter(",");setRecordSeparatorPolicy(mulitiLineRecordSeparatorPolicy);setLineMapper(defaultLineMapper);} }3、自定義FieldSetMapper
自定義CommonFieldSetMapper
*** @author shuliangzhao* @date 2020/12/4 22:14*/ public class CommonFieldSetMapper<T> implements FieldSetMapper<T> {private Class<? extends T> type;@Overridepublic T mapFieldSet(FieldSet fieldSet) throws BindException {try {T t = type.newInstance();Field[] declaredFields = type.getDeclaredFields();if (declaredFields != null) {for (Field field : declaredFields) {field.setAccessible(true);if (field.getName().equals("id")) {continue;}String name = field.getType().getName();if (name.equals("java.lang.Integer")) {field.set(t,fieldSet.readInt(field.getName()));}else if (name.equals("java.lang.String")) {field.set(t,fieldSet.readString(field.getName()));}else if (name.equals("java.util.Date")) {field.set(t,fieldSet.readDate(field.getName()));}else{field.set(t,fieldSet.readString(field.getName()));}}return t;}} catch (Exception e) {e.printStackTrace();}return null;}public void setTargetType(Class<? extends T> type) {this.type = type;}4、讀跨多行文件processor
PartitonMultiFileProcessor 詳細如下
@Component @StepScope public class PartitonMultiFileProcessor implements ItemProcessor<CreditBill,CreditBill> {@Overridepublic CreditBill process(CreditBill item) throws Exception {CreditBill creditBill = new CreditBill();creditBill.setAcctid(item.getAcctid());creditBill.setAddress(item.getAddress());creditBill.setAmout(item.getAmout());creditBill.setDate(item.getDate());creditBill.setName(item.getName());return creditBill;} }5、讀跨多行文件writer
PartitionMultiFileWriter詳細如下
@Component @StepScope public class PartitionMultiFileWriter implements ItemWriter<CreditBill> {@Autowiredprivate CreditBillMapper creditBillMapper;@Overridepublic void write(List<? extends CreditBill> items) throws Exception {if (items != null && items.size() > 0) {items.stream().forEach(item -> {creditBillMapper.insert(item);});}} }至此,我們完成了對跨行讀文件的處理。
如果想更詳細查看以上所有代碼請移步到github:讀跨多行文件詳細代碼
總結
以上是生活随笔為你收集整理的全网最详细SpringBatch读(Reader)跨多行文件讲解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 全网最详细SpringBatch批处理读
- 下一篇: 全网最详细SpringBatch读(Re