文章列表

  • 读记录跨多行文件
    • 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)跨多行文件讲解相关推荐

  1. 全网最详细SpringBatch读(Reader)混合文件讲解

    文章列表 一.读混合记录文件 1.FieldSetMapper实现 2.LineTokenizer实现 3.混合读reader实现类 4.读混合文件job配置 5.读混合文件processor 6.读 ...

  2. 全网最详细SpringBatch批处理读取分区(Paratition)文件讲解

    文章目录 一.分区Step 1.数据分区 2.分区处理 二.实现分区关键接口 1.Partitioner 2.StepExecutionSplitter 3.PartitionHandler 三.基本 ...

  3. java实现txt文件/文本转语音(全网最详细易懂)

    java实现txt文件/文本转语音(全网最详细易懂) 1.下载依赖包 https://github.com/freemansoft/jacob-project/releases 2.将ddl文件放到j ...

  4. “是男人就下一百层”h5游戏全网最详细教学、全代码,js操作

    "是男人就下一百层"h5游戏全网最详细教学.全代码,js操作 博主的话 游戏展示 编程工具介绍 游戏代码 代码讲解 js 第一步 切换div的显示与隐藏 js 第二步 在菜单页面用 ...

  5. SpringBatch读文件(FlatFileItemReader)写据库(MyBatisBatchItemWriter)(四)

    文章目录 一.抽取顺序读取数据库公共Writer 二.mapper配置文件 三.写数据库的job 四.继承公共CommonProcesor 五.执行job 前言:我们在日常开发中可能会遇到写数据库,S ...

  6. 一个全网最详细的Python教程

    光从编程的难易度来说,Python 简单&易学,零基础.跨专业都很容易上手.(想学全网最详细 Python 教程,那一定要看看哦~) 从就业前景来看,很多个领域都使用了 Python ,比如大 ...

  7. 很多的朋友问我这个零基础应该怎么开始学英文,这里给出全网最详细的操作步骤和用书,

    很多的朋友问我这个零基础应该怎么开始学英文,这里给出全网最详细的操作步骤和用书, 建议大家收藏后跟着做, 第一步:学会26个英文字母的标准发音, 第二步:学会48个国际音标的读音, 并且,学会用音标去 ...

  8. 赢在微点答案专区英语_高考英语怎么拿140+?全网最详细分阶段学习方法!

    作者介绍: 小胖学长,毕业于某省重点高中,在校期间英语单科多次排名年级前列.全国一卷高考英语145,现就读于西南政法大学. "在高中阶段所有学科中,英语是提分性价比最高的科目.只要你有付出, ...

  9. Office Online Server搭建(全网最详细)

    前言 最近换新公司了,一直挺忙的,好久没正儿八经的吹牛逼了!新公司技术部门有定期学习计划,和技术储备计划,这不来了个在线预览文档的活么,作为公司技术储备,需求产生的背景:公司Word.Excel.PD ...

最新文章

  1. 数据库分析函数 MySQL_MySql数据库索引分析explain函数的使用
  2. 一个学术 导航网站----科塔学术
  3. 今天,你比赛加班了吗?
  4. 调用startActivityForResult,onActivityResult无响应的问题
  5. 新的一年,对产品和产品经理的感悟
  6. Docker 更换下载镜像源
  7. JZOJ 5930. 【NOIP2018模拟10.26】山花
  8. matlab 设计带阻型陷波滤波器_Q值可调、最大增益恒定的带通滤波器
  9. VS2010 Resource view为空的解决办法
  10. 常用类 (一) ----- Arrays数组工具类
  11. 【免费毕设】asp.netERP客户关系系统设计(源代码+lunwen)
  12. Git可视化极简易教程 —— Git GUI使用方法
  13. mysql mysql.sock连接_【MySQL】mysql.sock文件作用
  14. 查询计算机ip地址的方法,计算机的ip地址查询的几种简单方法介绍
  15. 教小师妹学多线程,看完我写的例子,脸红成那样!
  16. C语言经典面试题 与 C语言面试宝典
  17. 两种操作botton的方法
  18. 「管理数学基础」2.3 泛函分析:赋范空间与巴拿赫空间
  19. 利用PDF编辑软件给PDF添加页码的操作全过程
  20. 数仓工具—Hive实战之拉链表(3)

热门文章

  1. WCHAR,CHAR,TCHAR的区别
  2. mysql show processlist host_show processlist host 为 百分号(%)
  3. python最新功能_Python在2020的新增功能:第1部分
  4. mysql db python_python下的MySQLdb使用
  5. 工业用微型计算机(16)-指令系统(11)
  6. 【论文解读】CVPR 2021 | 旷视提出GID:用于目标检测的通用实例蒸馏
  7. 我总结的120页《图解MIT线性代数笔记.pdf》,都是干货!
  8. 数据分析:第一轮返工潮,哪些城市疫情传播压力最大
  9. 首发:吴恩达的 CS229的数学基础(线性代数),有人把它做成了在线翻译版本!...
  10. 技术干货 | 视频直播关键技术和趋势