天天看點

Spring Batch 之 Sample(固定長格式檔案讀寫)(六)

      前篇關于Spring Batch的文章,講述了Spring Batch 對XML檔案的讀寫操作。 本文将通過一個完整的執行個體,與大家一起讨論運用Spring Batch對固定長格式檔案的讀寫操作。執行個體延續前面的例子,讀取一個含有四個字段的TXT檔案(ID,Name,Age,Score),對讀取的字段做簡單的處理,然後輸出到另外一個TXT檔案中。

      工程結構如下圖:

Spring Batch 之 Sample(固定長格式檔案讀寫)(六)

      applicationContext.xml和log4j.xml前文已經叙述過,在此不做贅述。

      本文核心配置檔案batch.xml内容如下:

<?xml version="1.0" encoding="UTF-8"?>
 <bean:beans xmlns="http://www.springframework.org/schema/batch"
     xmlns:bean="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx"
     xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
     xmlns:util="http://www.springframework.org/schema/util"
     xsi:schemaLocation="http://www.springframework.org/schema/beans 
 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
 http://www.springframework.org/schema/tx 
 http://www.springframework.org/schema/tx/spring-tx-3.0.xsd  
 http://www.springframework.org/schema/aop 
 http://www.springframework.org/schema/aop/spring-aop-3.0.xsd  
 http://www.springframework.org/schema/context 
 http://www.springframework.org/schema/context/spring-context-2.5.xsd
 http://www.springframework.org/schema/batch 
 http://www.springframework.org/schema/batch/spring-batch-2.1.xsd 
 http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
 
     <bean:import resource="applicationContext.xml" />
 
     <!-- Job資訊的配置 -->
     <job id="fixedLengthJob">
         <step id="fixedLengthStep">
             <tasklet>
                 <chunk reader="fixedLengthReader" writer="fixedLengthWriter"
                     processor="fixedLengthProcessor" commit-interval="10">
                 </chunk>
             </tasklet>
         </step>
     </job>
 
     <!-- 固定長檔案的讀資訊的配置 -->
     <bean:bean id="fixedLengthReader"
         class="org.springframework.batch.item.file.FlatFileItemReader" scope="step">
         <bean:property name="resource"
             value="file:#{jobParameters['inputFilePath']}" />
         <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="studentBean"/>
                     </bean:bean>
                 </bean:property>
             </bean:bean>
         </bean:property>
     </bean:bean>
     <bean:bean id="studentBean"
         class="com.wanggc.springbatch.sample.fixedlength.StudentPojo" scope="prototype" />
     <bean:bean id="lineTokenizer"
         class="org.springframework.batch.item.file.transform.FixedLengthTokenizer">
         <bean:property name="columns" value="1-6,7-15,16-18,19-" />
         <bean:property name="names" value="ID,name,age,score" />
     </bean:bean>
 
     <!-- 固定長格式檔案的寫 -->
     <bean:bean id="fixedLengthWriter"
         class="org.springframework.batch.item.file.FlatFileItemWriter" scope="step">
         <bean:property name="resource"
             value="file:#{jobParameters['outputFilePath']}" />
         <bean:property name="lineAggregator">
             <bean:bean
 class="org.springframework.batch.item.file.transform.FormatterLineAggregator">
                 <bean:property name="fieldExtractor">
                     <bean:bean
 class="org.springframework.batch.item.file.transform.BeanWrapperFieldExtractor">
                         <bean:property name="names" value="ID,name,age,score" />
                     </bean:bean>
                 </bean:property>
                 <bean:property name="format" value="%-9s%-20s%3d%-2.0f" />
             </bean:bean>
         </bean:property>
     </bean:bean>
 </bean:beans>      

       22-30行配置了Job的基本資訊。此Job包含一個Step,Step中包含了基本的讀(fixedLengthReader),處理(fixedLengthProcessor),寫(fixedLengthWriter)以及commit件數(commit-interval)。

      33-49行配置了讀處理的詳細資訊。固定長格式和csv格式都屬于flat檔案格式,是以讀取固定長格式檔案也是需要使用Spring Batch提供的核心類FlatFileItemReader。對此類的配置在《Spring Batch 之 Sample(CSV檔案操作)(四) 》中已經做過詳細說明。但要注意lineTokenizer的配置,在讀取CSV檔案的時候,使用的是DelimitedLineTokenizer類,但是讀取固定長格式的檔案,需要使用FixedLengthTokenizer,如52-56行所示。其columns是如何分割一條記錄資訊,也就是說指定哪幾列屬于一個項目的資訊(注意:列數的總長度與檔案記錄長度不一樣的時候,會報錯。注意限定範圍)。屬性names指定每個項目的名字。其名字與44行prototypeBeanName屬性指定的Pojo屬性名相同。

      59-76行配置了寫處理的詳細資訊。寫固定長格式的檔案,與寫CSV格式的檔案一樣,也是使用Spring Batch提供的核心類FlatFileItemWriter。在此也不再贅述。但要注意lineAggregator屬性使用的是FormatterLineAggregator類,此類的format屬性可以指定每個項目所占的長度和格式。

      batch.xml檔案配置了對固定長檔案的和寫。在讀之後,寫之前的處理,是通過自定的FixedLengthProcessor 類處理的。詳細代碼如下:

Spring Batch 之 Sample(固定長格式檔案讀寫)(六)
package com.wanggc.springbatch.sample.fixedlength;

import org.springframework.batch.item.ItemProcessor;
import org.springframework.stereotype.Component;

/**
 * 業務處理類。
 * 
 * @author Wanggc
*/
@Component("fixedLengthProcessor")
public class FixedLengthProcessor implements
        ItemProcessor<StudentPojo, StudentPojo> {

/**
     * 對取到的資料進行簡單的處理。
     * 
     * @param student
     *            處理前的資料。
     * @return 處理後的資料。
     * @exception Exception
     *                處理是發生的任何異常。
*/
public StudentPojo process(StudentPojo 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;
    }

}      
Spring Batch 之 Sample(固定長格式檔案讀寫)(六)

      至此,對固定長格式檔案的讀、處理、寫操作已經介紹完畢。下面是一些輔助檔案的資訊。

      Pojo類StudentPojo的詳細代碼如下:

Spring Batch 之 Sample(固定長格式檔案讀寫)(六)
package com.wanggc.springbatch.sample.fixedlength;

/** Pojo類_Student */
public class StudentPojo {
/** ID */
private String ID = "";
/** 名字 */
private String name = "";
/** 年齡 */
private int age = 0;
/** 分數 */
private float score = 0;
/* 為節省篇幅,getter 和 setter 已經删除 */    
}      
Spring Batch 之 Sample(固定長格式檔案讀寫)(六)

      Job啟動類Launch的詳細代碼如下:

Spring Batch 之 Sample(固定長格式檔案讀寫)(六)
package com.wanggc.springbatch.sample.fixedlength;

import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobParametersBuilder;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Launch {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext(
"batch.xml");
        JobLauncher launcher = (JobLauncher) context.getBean("jobLauncher");
        Job job = (Job) context.getBean("fixedLengthJob");

        try {
            // JOB實行
            JobExecution result = launcher.run(
                    job,
                    new JobParametersBuilder()
                            .addString("inputFilePath",
"C:\\testData\\fixedLengthInputFile.txt")
                            .addString("outputFilePath",
"C:\\testData\\fixedLengthOutputFile.txt")
                            .toJobParameters());
            // 運作結果輸出
            System.out.println(result.toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}      
Spring Batch 之 Sample(固定長格式檔案讀寫)(六)

      input檔案内容如下:

Spring Batch 之 Sample(固定長格式檔案讀寫)(六)

     處理結果如下:

Spring Batch 之 Sample(固定長格式檔案讀寫)(六)

     下次,将和大家一起讨論關于Spring Batch 對複合格式檔案的讀寫問題。