我正在调查使用spring批处理从编码的压缩文件处理记录。记录是可变长度的,其中嵌套了可变长度数据字段。
我是Spring和Spring Batch的新手,这就是我计划构建批量配置的方式。
我最初的问题是了解如何设置ItemReader,我已经看了一些使用FlatFileItemReader的例子,但我的困难是期望有一个Line Mapper。在我的情况下,我不知道如何做到这一点(文件中没有一行的概念)。
有一些articles表示使用自定义的BufferedReaderFactory,但很高兴看到一个有用的例子。
帮助将不胜感激。
答案 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
添加其他类似方法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中压缩并编码的文件读取行的简单配置是否有效。
要点:
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()方法中处理该流。