我在批处理Spring项目中定义了一个作业流程,并定义了$f='data.txt';
$fh=fopen($f,'r+');
while (($l=fgets($fh))!==false) file_put_contents('tmp',clean($l),FILE_APPEND);
fclose($f);
unlink($f);
rename('tmp',$f);
,ItemReader
,ItemProcessor
等。
我的ItemWriter
代码如下:
ItemReader
我的文件输入格式为:
@Component
@StepScope
public class MyFileReader extends FlatFileItemReader<FileInfo> {
private String fileName;
public MyFileReader () {
}
@Value("#{jobParameters[fileName]}")
public void setFileName(final String fileName) {
this.fileName = fileName;
}
@Override
public void afterPropertiesSet() throws Exception {
Resource resource = new FileSystemResource(fileName);
setResource(resource);
setEncoding("UTF-8");
super.afterPropertiesSet();
}
}
我想阅读文件的所有行并将 行和文件地址 返回111111,11111,111,111
222222,22222,222,222
,但是{{1}逐行读取。我该怎么做?是否重写ItemProcessor
方法并手动处理问题?
答案 0 :(得分:2)
如果我理解了这个问题,你想要从文件中读取所有行,将该数据存储在一个对象中,然后将所述对象传递给处理器。一种方法是在作业开始之前使用Job Listener读取文件中的所有行。如下图所示,您可以读取所有行,填充表示单行内容的Java对象,收集所有这些对象(如果有两行,则“填充2个bean”),然后传递它们一次一个处理器(如果你愿意,可能同时处理)。它看起来像这样:
首先,您将创建一个侦听器。
public class MyJobListenerImpl implements JobExecutionListener {
private MyFileReader reader;
@Override
public void beforeJob(JobExecution jobExecution) {
reader.init();
}
@Override
public void afterJob(JobExecution jobExecution) {
// noop
}
// Injected
public void setReader(MyFileReader reader) {
this.reader = reader;
}
接下来,在您的自定义阅读器中添加一个init方法。
public void init() {
if(Files.exists(inputFileLocation)) {
List<String> inputData = null;
try {
inputData = Files.readAllLines(inputFileLocation, StandardCharsets.UTF_8);
} catch(IOException e) {
System.out.println("issue reading input file {}. Error message: {}", inputFileLocation, e);
throw new IllegalStateException("could not read the input file.");
}
try {
for(String fileItem : inputData) {
YourFileDataBean fileData = new YourFileDataBean();
yourFileDataBean.setField1(fileItem.split(",")[0].trim());
yourFileDataBean.setFiled2(fileItem.split(",")[1].trim());
yourFileDataBean.setField3(fileItem.split(",")[2].trim());
yourFileDataBean.setField4(fileItem.split(",")[3].trim());
myDeque.add(yourFileDataBean); // really up to you how you want to store your bean but you could add a Deque instance variable and store it there.
}
} catch(ArrayIndexOutOfBoundsException e) {
LOGGER.warn("ArrayIndexOutOfBoundsException due to data in input file.");
throw new IllegalStateException("Failure caused by init() method. Error reading in input file.");
}
} else {
LOGGER.warn("Input file {} does not exist.", inputFileLocation);
throw new IllegalStateException("Input file does not exist at file location " + inputFileLocation);
}
}
使自定义阅读器中的read()(或MyFileReader())方法返回由读入的所有文件行填充的对象。在此示例中,我实现了ItemReader而不是像您一样扩展它,但是你明白了。如果您打算返回表示整个文件的单个Java对象,则不需要将对象存储在Deque或List中。
@Override
public MyFileReader read() throws NonTransientResourceException {
return myDeque.poll();
}
希望这会有所帮助。
将文件地址返回给ItemProcessor。您可以将此字段设置为YourFileDataBean并在其中存储inputFileLocation,或将其保存到执行上下文并以此方式访问它。如果将此文件路径注入到阅读器中,您可以在处理器中执行相同的操作,假设您的阅读器在确定文件路径时没有任何作用(也就是说,它是预定的)。