Spring Batch处理编码的压缩文件

时间:2015-08-13 09:27:51

标签: spring-batch

我正在调查使用spring批处理从编码的压缩文件处理记录。记录是可变长度的,其中嵌套了可变长度数据字段。

我是Spring和Spring Batch的新手,这就是我计划构建批量配置的方式。

  • ItemReader需要将压缩的(* .gz)文件输入流中的单个记录读入POJO(字节数组),该记录的长度将包含在流的前两个字节中。
  • ItemProcessor将解码字节数组并将信息存储在POJO中的相关属性中。
  • ItemWriter将填充数据库。

我最初的问题是了解如何设置ItemReader,我已经看了一些使用FlatFileItemReader的例子,但我的困难是期望有一个Line Mapper。在我的情况下,我不知道如何做到这一点(文件中没有一行的概念)。

有一些articles表示使用自定义的BufferedReaderFactory,但很高兴看到一个有用的例子。

帮助将不胜感激。

4 个答案:

答案 0 :(得分:3)

如果gzip文件是一个简单的txt文件,你只需要一个custum BufferedReaderFactory,然后linemaper获取当前行的String

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.GZIPInputStream;
import org.springframework.batch.item.file.BufferedReaderFactory;
import org.springframework.core.io.Resource;

public class GZipBufferedReaderFactory implements BufferedReaderFactory {

    /** Default value for gzip suffixes. */
    private List<String> gzipSuffixes = new ArrayList<String>() {

        {
            add(".gz");
            add(".gzip");
        }
    };

    /**
     * Creates Bufferedreader for gzip Resource, handles normal resources
     * too.
     * 
     * @param resource
     * @param encoding
     * @return
     * @throws UnsupportedEncodingException
     * @throws IOException 
     */
    @Override
    public BufferedReader create(Resource resource, String encoding)
            throws UnsupportedEncodingException, IOException {
        for (String suffix : gzipSuffixes) {
            // test for filename and description, description is used when 
            // handling itemStreamResources
            if (resource.getFilename().endsWith(suffix)
                    || resource.getDescription().endsWith(suffix)) {
                return new BufferedReader(new InputStreamReader(new GZIPInputStream(resource.getInputStream()), encoding));
            }
        }
        return new BufferedReader(new InputStreamReader(resource.getInputStream(), encoding));
    }

    public List<String> getGzipSuffixes() {
        return gzipSuffixes;
    }

    public void setGzipSuffixes(List<String> gzipSuffixes) {
        this.gzipSuffixes = gzipSuffixes;
    }
}

简单的itemreader配置:

 <bean id="itemReader" class="org.springframework.batch.item.file.FlatFileItemReader" scope="step">
  <property name="resource" value="#{jobParameters['input.file']}" />
  <property name="lineMapper">
    <bean class="org.springframework.batch.item.file.mapping.PassThroughLineMapper" />
  </property>
  <property name="strict" value="true" />
  <property name="bufferedReaderFactory">
    <bean class="your.custom.GZipBufferedReaderFactory" />
  </property>
</bean>

答案 1 :(得分:1)

从功能请求票证到春季批次(https://jira.spring.io/browse/BATCH-1750):

kia_save_extra_details()

自定义public class GZIPResource extends InputStreamResource implements Resource { public GZIPResource(Resource delegate) throws IOException { super(new GZIPInputStream(delegate.getInputStream())); } } 不会使用GZipBufferedReaderFactory以外的其他人。

编辑:懒人版。在调用FlatFileItemReader之前,这不会尝试打开文件。如果您在程序初始化时创建资源(例如使用自动装配),则可以避免由于文件不存在而导致的异常。

getInputStream

Edit2:这仅适用于输入资源

添加其他类似方法public class GzipLazyResource extends FileSystemResource implements Resource { public GzipLazyResource(File file) { super(file); } public GzipLazyResource(String path) { super(path); } @Override public InputStream getInputStream() throws IOException { return new GZIPInputStream(super.getInputStream()); } } 无法正常工作,因为春天使用的是getOutputStream,而不是FileSystemResource.getFile

答案 2 :(得分:1)

测试了这种从S3中压缩并编码的文件读取行的简单配置是否有效。

要点:

  • 实施一个使用Apache FileInfo fileInfo = new FileInfo(filePath); using (ExcelPackage excel = new ExcelPackage(fileInfo)) { var worksheet = excel.Workbook.Worksheets.First(); string cellName = worksheet.Cells[i, colDate].ToString(); // = "A2"- correct cell string cellValue= worksheet.Cells[i, colDate].Value.ToString(); // = "42874.6666666667" } 的{​​{1}},并将其设置为BufferedReaderFactory上的bufferedReaderFactory。
  • 使用GZIPInputStreamFactory从Spring Cloud配置FlatFileItemReader,并使用它在S3中获取压缩后的平面文件。将其设置为SimpleStorageResourceLoader上的资源。

注意:读入字符串可以很容易地通过读入POJO来替换。

GZIPBufferedReaderFactory.java

使用Apache的AmazonS3Client

FlatFileItemReader

AWSConfiguration.java

GZIPInputStreamFactory

public class GZIPBufferedReaderFactory implements BufferedReaderFactory { private final GZIPInputStreamFactory gzipInputStreamFactory; public GZIPBufferedReaderFactory(GZIPInputStreamFactory gzipInputStreamFactory) { this.gzipInputStreamFactory = gzipInputStreamFactory; } @Override public BufferedReader create(Resource resource, String encoding) throws IOException { return new BufferedReader(new InputStreamReader(gzipInputStreamFactory.create(resource.getInputStream()), encoding)); } } @Configuration public class AWSConfiguration { @Bean public AmazonS3Client s3Client(AWSCredentialsProvider credentials, Region region) { ClientConfiguration clientConfig = new ClientConfiguration(); AmazonS3Client client = new AmazonS3Client(credentials, clientConfig); client.setRegion(region); return client; } } Bean的配置方式可能会有所不同,由于其他地方有文档,因此在此不再赘述。

BatchConfiguration.java

AWSCredentialsProvider

答案 3 :(得分:0)

我的困惑是基于自定义ItemReader中的文件处理,如果我要在read()方法中打开并处理文件,我将不得不跟踪我在文件中的位置等。我设法通过在自定义ItemReader的构造函数中创建BufferedInputStream(BufferedInputStream(new GZIPInputStream(new FileInputStream(file))来解决此问题,然后在每次迭代步骤中在read()方法中处理该流。