本文将通过一个完整的实例,与大家一起讨论运用Spring Batch对CSV文件的读写操作。此实例的流程是:读取一个含有四个字段的CSV文件(ID,Name,Age,Score),对读取的字段做简单的处理,然后输出到另外一个CSV文件中。

工程结构如下图:

JobLaunch类用来启动Job, CsvItemProcessor类用来对Reader取得的数据进行处理, Student类是一个POJO类,用来存放映射的数据。 inputFile.csv是数据读取文件, outputFile.csv是数据输出文件。

application.xml文件配置如前篇文章,不再赘述。

batch.xml文件中Job配置如下:

<job id="csvJob">
<step id="csvStep">
<tasklet transaction-manager="transactionManager">
<chunk reader="csvItemReader" writer="csvItemWriter" processor="csvItemProcessor" commit-interval="1">
</chunk>
</tasklet>
</step>
</job>

这个文件里配置了这次运行的JOB:csvJob。本Job包含一个Step,完成一个完整的CSV文件读写功能。分别由 csvItemReader完成CSV文件的读操作,由 csvItemProcessor完成对取得数据的处理,由 csvItemWriter完成对CSV文件的写操作。

batch.xml文件中csvItemReader配置如下:

<!-- 读取csv文件 -->
<bean:bean id="csvItemReader"
class="org.springframework.batch.item.file.FlatFileItemReader" scope="step">
<bean:property name="resource" value="classpath:inputFile.csv"/>
<bean:property name="lineMapper">
<bean:bean
class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
<bean:property name="lineTokenizer" ref="lineTokenizer"/>
<bean:property name="fieldSetMapper">
<bean:bean
class="org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper">
<bean:property name="prototypeBeanName" value="student"></bean:property>
</bean:bean>
</bean:property>
</bean:bean>
</bean:property>
</bean:bean> <bean:bean id="student" class="com.wanggc.springbatch.sample.csv.Student"></bean:bean> <!-- lineTokenizer -->
<bean:bean id="lineTokenizer" class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
<bean:property name="delimiter" value=","/>
<bean:property name="names">
<bean:list>
<bean:value>ID</bean:value>
<bean:value>name</bean:value>
<bean:value>age</bean:value>
<bean:value>score</bean:value>
</bean:list>
</bean:property>
</bean:bean>

csvItemReader实现的是Spring Batch提供FlatFileItemReader类,此类主要用于Flat文件的读操作。它包含两个必要的属性 resource和 lineMapper。前者指定要读取的文件的位置,后者是将文件的每一行映射成一个Pojo对象。其中 lineMapper也有两个重要属性 lineTokenizer和 fieldSetMapper, lineTokenizer将文件的一行分解成一个 FieldSet,然后由 fieldSetMapper映射成Pojo对象。

这种方式与DB的读操作非常类似。lineMapper类似于ResultSet,文件中的一行类似于Table中的一条记录,被封装成的FieldSet,类似于RowMapper。至于怎么将一条记录封装,这个工作由lineTokenizer的继承类DelimitedLineTokenizer完成。DelimitedLineTokenizer的delimiter属性决定文件的一行数据按照什么分解,默认的是“,”, names属性标示分解的每个字段的名字,传给fieldSetMapper(本实例用的是BeanWrapperFieldSetMapper)的时候,就可以按照这个名字取得相应的值。fieldSetMapper的属性prototypeBeanName,是映射Pojo类的名字。设置了此属性后,框架就会将lineTokenizer分解成的一个FieldSet映射成Pojo对象,映射是按照名字来完成的(lineTokenizer分解时标注的名字与Pojo对象中字段的名字对应)。

总之,FlatFileItemReader读取一条记录由以下四步完成:1,从resource指定的文件中读取一条记录;2,lineTokenizer将这条记录按照delimiter分解成Fileset,每个字段的名字由names属性取得;3,将分解成的Fileset传递给fieldSetMapper,由其按照名字映射成Pojo对象;4,最终由FlatFileItemReader将映射成的Pojo对象返回,框架将返回的对象传递给Processor。

csvItemProcessor实现的是ItemProcessor类。此类接受Reader映射成的Pojo对象,可以对此对象做相应的业务逻辑处理,然后返回,框架就会将返回的结果传递给Writer进行写操作。具体实现代码如下:

package com.wanggc.springbatch.sample.csv;

import org.springframework.batch.item.ItemProcessor;
import org.springframework.stereotype.Component; /**
* ItemProcessor类。
*/
@Component("csvItemProcessor")
public class CsvItemProcessor implements ItemProcessor<Student, Student> { /**
* 对取到的数据进行简单的处理。
*
* @param student
* 处理前的数据。
* @return 处理后的数据。
* @exception Exception
* 处理是发生的任何异常。
*/
@Override
public Student process(Student student) throws Exception {
/* 合并ID和名字 */
student.setName(student.getID() + "--" + student.getName());
/* 年龄加2 */
student.setAge(student.getAge() + 2);
/* 分数加10 */
student.setScore(student.getScore() + 10);
/* 将处理后的结果传递给writer */
return student;
}
}

batch.xml文件中csvItemReader配置如下:

<!-- 写CSV文件 -->
<bean:bean id="csvItemWriter"
class="org.springframework.batch.item.file.FlatFileItemWriter" scope="step">
<bean:property name="resource" value="file:src/outputFile.csv"/>
<bean:property name="lineAggregator">
<bean:bean
class="org.springframework.batch.item.file.transform.DelimitedLineAggregator">
<bean:property name="delimiter" value=","></bean:property>
<bean:property name="fieldExtractor">
<bean:bean
class="org.springframework.batch.item.file.transform.BeanWrapperFieldExtractor">
<bean:property name="names" value="name,age,score"></bean:property>
</bean:bean>
</bean:property>
</bean:bean>
</bean:property>
</bean:bean>

csvItemWriter实现的是FlatFileItemWriter类。此类与FlatFileItemReader类相似,也有两个重要的属性:resource和lineAggregator。前者是要输出的文件的路径,后者和lineTokenizer类似。lineAggregator(本实例用DelimitedLineAggregator类)也有两个重要的属性:delimiter和fieldExtractor。Delimiter标示输出的字段以什么分割,后者将Pojo对象组装成由Pojo对象的字段组成的一个字符串。同样FlatFileItemWriter写一条记录也有以下四步完成:1,Processor传递过来一个对象给lineAggregator;2,lineAggregator将其这个对象转化成一个数组;3,再由lineAggregator的属性fieldExtractor将数组转化成按照delimiter分割一个字符串;4,将这个字符串输出。

这样,一条数据的读、处理、写操作就基本完成了。当然,读和写也可以自己写类来处理,只是要注意继承FlatFileItemReader和FlatFileItemWriter就可以了。

实例中用到的Student类代码如下:

package com.wanggc.springbatch.sample.csv;

/** Pojo类_Student */
public class Student {
/** ID */
private String ID = "";
/** 名字 */
private String name = "";
/** 年龄 */
private int age = 0;
/** 分数 */
private float score = 0;
/*getter 和setter已删除*/
}

实例中用到的输入数据如下:

实例输出结果如下:

本文的配置要注意以下两点:

1,  注意Writer的resource要写成“file:******”形式,不能用“classpath:******”形式。

2,  如果将Job配置中commit-interval属性配置为大于1时,每次commit的都是最后一条记录,前面读取的被覆盖了。具体原因不明,如果将Reader的fieldSetMapper属性自己重写,就可以解决这个问题。(注:student bean添加scope属性可以解决此问题:scope:"prototype".2011/12/16)

下次,将和大家一起讨论关于XML文件的读写问题。

作者:孤旅者
如果本文使您有所收获,请点击右下角的 [推荐]!
如果您对本文有意见或者建议,欢迎留言,哪怕是拍砖(^_^)!
欢迎转载,请注明出处!
感谢您的阅读,请关注后续博客!

SpringBatch Sample (二)(CSV文件操作)的更多相关文章

  1. java csv 文件 操作类

    一个CSV文件操作类,功能比较齐全: package tool; import java.io.BufferedReader; import java.io.BufferedWriter; impor ...

  2. C语言第十二讲,文件操作.

    C语言第十二讲,文件操作. 一丶文件操作概述 在操作系统中,我们的文档都称为文件.操作系统也为我们提供了接口进行操作.不同语言都是使用的相同的接口,只不过封装的上层接口不一样 操作文件的步骤 打开文件 ...

  3. [Python Study Notes]csv文件操作

    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ...

  4. Python csv文件操作

    一.open文件打开和with open as 文件打开的区别 file= open("test.txt","r") try: for line in file ...

  5. 使用Python对Csv文件操作

    csv是Comma-Separated Values的缩写,是用文本文件形式储存的表格数据,比如如下的表格: 就可以存储为csv文件,文件内容是: No.,Name,Age,Score 1,mayi, ...

  6. 《Java核心技术卷二》笔记(二)文件操作和内存映射文件

    文件操作 上一篇已经总结了流操作,其中也包括文件的读写.文件系统除了读写以为还有很多其他的操作,如复制.移动.删除.目录浏览.属性读写等.在Java7之前,一直使用File类用于文件的操作.Java7 ...

  7. 一个封装好的CSV文件操作C#类代码

    using System.Data; using System.IO; namespace DotNet.Utilities { /// <summary> /// CSV文件转换类 // ...

  8. csv文件操作

    1.python2中: import csv infos = [ ['peter','male'], ['marry','female'], ['johon','male'], ['rose','fe ...

  9. python学习笔记(二)文件操作和集合

    集合: 集合也是一种数据类型,一个类似列表东西,它的特点是无序的,不重复的,也就是说集合中是没有重复的数据 集合的作用: 1.它可以把一个列表中重复的数据去掉,而不需要你再写判断 2.可以做关系测试, ...

随机推荐

  1. 动态BT跳转

    METHOD eh_onzobject_id_link. ***定义 DATA : lv_crmt_object_guid TYPE crmt_object_guid, lv_index TYPE i ...

  2. 第 4 章 用 HTML5 建立超链接

    HTML 文件中最重要的应用之一就是超链接.—— 当鼠标单击一些文字.图片或其他网页元素时,浏览器会根据其指示载入一个新的页面或跳转到页面的其他位置. 超链接除了可链接文本外,也可链接各种媒体,如声音 ...

  3. OCP知识点讲解 之 检查点队列与增量检查点

    原创 http://blog.chinaunix.net/uid-26762723-id-3271558.html 检查点的主要目的是以对数据库的日常操作影响最小的方式刷新脏块.脏块不断的产生,如何将 ...

  4. maven聚合工程使用如何debug

    maven聚合工程在正常情况下,使用debug时会出错,因为没有源码,就不会显示代码和断点行数条. 进行如下操作: 默认情况下source下只有默认的default文件夹,点击remove进行删除(这 ...

  5. openstack安装指南和在centos7上的安装指南

    openstack安装指南官网:http://docs.openstack.org/project-install-guide/newton/ openstack在centos7上的安装指南官网:ht ...

  6. ISO/OSI七层网络参考模型、TCP/IP四层网络模型和教学五层网络模型

    一.说明 直接的原因是昨晚<计算机网络(自顶向下方法)>到货了,以为能讲得有些不一样,但看完整本也就是老调地讲过来讲应用层.传输层.网络层.网络接口层.感觉比之谢希仁的<计算机网络& ...

  7. OllyDbg安装教程

    1.下载 http://tools.pediy.com/windows/debuggers.htm 我们这里选择OllyDbg1.10下载 2.安装 解压下载的压缩包直接双击启动即可使用 3.插件安装 ...

  8. 谈一谈JUnit神奇的报错 java.lang.Exception:No tests found matching

    最近在学习Spring+SpringMVC+MyBatis,一个人的挖掘过程确实有点艰难,尤其是有一些神奇的报错让你会很蛋疼.特别是接触一些框架还是最新版本的时候,会因为版本问题出现很多错误,欢迎大家 ...

  9. 我个人对OOP的理解

    OOP面向对象的思维:pay1:封装 A.避免使用非法数据赋值 B.保证数据的完整性 C.避免类内部发生修改的时候,导致整个程序的修改 pay2:继承 A.继承模拟了现实世界的关系,OOP中强调一切皆 ...

  10. asp.net mvc如何获取url的相关信息

    1.获取完整url信息(协议名+域名+虚拟目录名+文件名+参数) string url = Request.Url.ToString(); 如: //1)获取完整url(协议名+域名+虚拟目录名+文件 ...