org.springframework.batch.item.ItemStreamException:文件不可写:Spring Batch

时间:2018-07-11 08:04:09

标签: spring spring-boot spring-batch

Spring Boot Batch 项目中,出现以下错误,不确定这里发生了什么问题?

我只是从mysql DB中读取表,然后使用FlatFileItemWriter将其写入文件。还使用Partiontioner读取代码并将其写入平面文件。 Spring Boot Parent版本2.0.2.RELEASE

org.springframework.batch.item.ItemStreamException: File is not writable: [C:\Spring_Learning\spring-batch\spring-batch-classic-db\csv\outputs\users.processed201-250.csv]
    at org.springframework.batch.item.util.FileUtils.setUpOutputFile(FileUtils.java:88) ~[spring-batch-infrastructure-4.0.1.RELEASE.jar:4.0.1.RELEASE]
    at org.springframework.batch.item.file.FlatFileItemWriter$OutputState.initializeBufferedWriter(FlatFileItemWriter.java:572) ~[spring-batch-infrastructure-4.0.1.RELEASE.jar:4.0.1.RELEASE]
    at org.springframework.batch.item.file.FlatFileItemWriter$OutputState.access$000(FlatFileItemWriter.java:414) ~[spring-batch-infrastructure-4.0.1.RELEASE.jar:4.0.1.RELEASE]
    at org.springframework.batch.item.file.FlatFileItemWriter.doOpen(FlatFileItemWriter.java:348) ~[spring-batch-infrastructure-4.0.1.RELEASE.jar:4.0.1.RELEASE]
    at org.springframework.batch.item.file.FlatFileItemWriter.open(FlatFileItemWriter.java:338) ~[spring-batch-infrastructure-4.0.1.RELEASE.jar:4.0.1.RELEASE]
    at org.springframework.batch.item.file.FlatFileItemWriter$$FastClassBySpringCGLIB$$bd919dcd.invoke(<generated>) ~[spring-batch-infrastructure-4.0.1.RELEASE.jar:4.0.1.RELEASE]
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) ~[spring-core-5.0.6.RELEASE.jar:5.0.6.RELEASE]
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:746) ~[spring-aop-5.0.6.RELEASE.jar:5.0.6.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.0.6.RELEASE.jar:5.0.6.RELEASE]
    at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:136) ~[spring-aop-5.0.6.RELEASE.jar:5.0.6.RELEASE]
    at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:124) ~[spring-aop-5.0.6.RELEASE.jar:5.0.6.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.6.RELEASE.jar:5.0.6.RELEASE]
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688) ~[spring-aop-5.0.6.RELEASE.jar:5.0.6.RELEASE]
    at org.springframework.batch.item.file.FlatFileItemWriter$$EnhancerBySpringCGLIB$$d3ba3d4f.open(<generated>) ~[spring-batch-infrastructure-4.0.1.RELEASE.jar:4.0.1.RELEASE]
    at org.springframework.batch.item.support.CompositeItemStream.open(CompositeItemStream.java:103) ~[spring-batch-infrastructure-4.0.1.RELEASE.jar:4.0.1.RELEASE]
    at org.springframework.batch.core.step.tasklet.TaskletStep.open(TaskletStep.java:310) ~[spring-batch-core-4.0.1.RELEASE.jar:4.0.1.RELEASE]
    at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:197) ~[spring-batch-core-4.0.1.RELEASE.jar:4.0.1.RELEASE]
    at org.springframework.batch.core.partition.support.TaskExecutorPartitionHandler$1.call(TaskExecutorPartitionHandler.java:139) [spring-batch-core-4.0.1.RELEASE.jar:4.0.1.RELEASE]
    at org.springframework.batch.core.partition.support.TaskExecutorPartitionHandler$1.call(TaskExecutorPartitionHandler.java:136) [spring-batch-core-4.0.1.RELEASE.jar:4.0.1.RELEASE]
    at java.util.concurrent.FutureTask.run(Unknown Source) [na:1.8.0_171]
    at java.lang.Thread.run(Unknown Source) [na:1.8.0_171]

代码

@Bean
    @StepScope
    public FlatFileItemWriter<Payments> slaveWriter(@Value("#{stepExecutionContext[fromId]}") final String fromId,
            @Value("#{stepExecutionContext[toId]}") final String toId) {

        FlatFileItemWriter<Payments> reader = new FlatFileItemWriter<>();
        reader.setResource(new FileSystemResource("csv/outputs/users.processed" + fromId + "-" + toId + ".csv"));
        reader.setAppendAllowed(true);

        reader.setLineAggregator(new DelimitedLineAggregator<Payments>() {
            {
                setDelimiter(",");
                setFieldExtractor(new BeanWrapperFieldExtractor<Payments>() {
                    {
                        setNames(new String[] { "customerNumber", "checkNumber", "paymentDate", "amount"});
                    }
                });
            }
        });
        return reader;
    }

2 个答案:

答案 0 :(得分:1)

尝试更新您的代码:

FlatFileItemWriter<Payments> writer = new FlatFileItemWriter<>();
        writer.setResource(new FileSystemResource("csv/outputs/users.processed" + fromId + "-" + toId + ".csv"));
        writer.setAppendAllowed(true);

收件人:

FlatFileItemWriter<Payments> writer = new FlatFileItemWriter<>();
        writer.setResource(new FileSystemResource("csv/outputs/users.processed" + fromId + "-" + toId + ".csv"));
        writer.setAppendAllowed(true);
        writer.setShouldDeleteIfEmpty(true);
        writer.setShouldDeleteIfExists(true);

我有同样的错误,对我有用。

有关详细信息,这是因为restarted的{​​{1}}参数可以在作业重新启动时设置为FileUtils.setUpOutputFile(File file, boolean restarted, boolean append, boolean overwriteOutputFile)。文件是从旧上下文中恢复的,并且不可写... 我不知道为什么。

答案 1 :(得分:0)

来自

的例外
if (!file.canWrite()) {
            throw new ItemStreamException("File is not writable: [" + file.getAbsolutePath() + "]");
}

File.canWrite如下 因此,请检查包括父母在内的路径,如果他们都具有“写”访问权限

/**
 138:    * This method test whether or not the current thread is allowed to
 139:    * write to this object.  This will be true if and only if 1) The
 140:    * <code>SecurityManager</code> (if any) allows write access to the
 141:    * file and 2) The file exists and 3) The file is writable.  To determine
 142:    * whether or not a non-existent file can be created, check the parent
 143:    * directory for write access.
 144:    *
 145:    * @return <code>true</code> if writing is allowed, <code>false</code> 
 146:    * otherwise
 147:    *
 148:    * @exception SecurityException If the <code>SecurityManager</code> 
 149:    * does not allow access to the file
 150:    */
 151:   public boolean canWrite()
 152:   {
 153:     // First do a SecurityCheck before doing anything else.
 154:     checkWrite();
 155:      
 156:     // Test for existence.  This is required by the spec
 157:     if (! VMFile.exists(path))
 158:       return false;
 159: 
 160:     if (VMFile.isDirectory(path))
 161:       return VMFile.canWriteDirectory(this);
 162:     else
 163:       return VMFile.canWrite(path);
 164:   }