如何使用Spring批处理FlatFileItemReader仅读取CSV文件中的子集列?

奥伦

我有一个知道如何读取具有14列的CSV文件的读者,我希望它能够接收具有许多列(〜500)的文件并仅读取这14列,我知道该解决方案应包括FieldSetMapper(根据这个问题:使用spring batch从csv文件中只读取选择性的列),但我找不到合适的示例。这是我目前的读者:

@Bean
public FlatFileItemReader<RowInput> csvRowsReader() {
    FlatFileItemReader<RowInput> reader = new FlatFileItemReader<>();
    Resource resource = new FileSystemResource(new File(FileManager.getInstance().getInputFileLocation()));
    reader.setResource(resource);

    reader.setLinesToSkip(1);
    reader.setLineMapper(new DefaultLineMapper<RowInput>(){{
        setLineTokenizer(new DelimitedLineTokenizer(){{
            setNames(new String[]{"Field_1", "Field_2", "Field_3", "Field_4", "Field_5",
                    "Field_6", "Field_7", "Field_8", "Field_9", "Field_10", "Field_11",
                    "Field_12", "Field_13", "Field_14"});
        }});
        setFieldSetMapper(new BeanWrapperFieldSetMapper<RowInput>(){{
            setTargetType(RowInput.class);
        }});
    }});


    reader.setLinesToSkip(1);
    return reader;
}

唯一的例外是:

原因:org.springframework.batch.item.file.transform.IncorrectTokenCountException:记录中发现的令牌数量不正确:预期为14个实际544

我尝试使用的FieldSetMapper:

    public class InputFieldSetMapper implements FieldSetMapper<RowInput>{

    public RowInput mapFieldSet(FieldSet fs) {

        if (fs == null) {
            return null;
        }

        RowInput input = new RowInput();
        input.setField1(fs.readString("Field_1"));
        input.setField2(fs.readString("Field_2"));
        // and so on...

        return input;
    }
}
Mahmoud Ben Hassine

您需要在上设置includedFields属性,LineTokenizer以指定在解析输入文件时要包括的字段。您的情况应该是这样的:

@Bean
public FlatFileItemReader<RowInput> csvRowsReader() {
    FlatFileItemReader<RowInput> reader = new FlatFileItemReader<>();
    Resource resource = new FileSystemResource(new File(FileManager.getInstance().getInputFileLocation()));
    reader.setResource(resource);

    reader.setLinesToSkip(1);
    reader.setLineMapper(new DefaultLineMapper<RowInput>(){{
        setLineTokenizer(new DelimitedLineTokenizer(){{
            setNames(new String[]{"Field_1", "Field_2", "Field_3", "Field_4", "Field_5",
                    "Field_6", "Field_7", "Field_8", "Field_9", "Field_10", "Field_11",
                    "Field_12", "Field_13", "Field_14"});
            setIncludedFields(0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10 ,11 ,12 ,13);
        }});
        setFieldSetMapper(new BeanWrapperFieldSetMapper<RowInput>(){{
            setTargetType(RowInput.class);
        }});
    }});

    return reader;
}

编辑:添加非顺序字段的示例

import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.file.FlatFileItemReader;
import org.springframework.batch.item.file.builder.FlatFileItemReaderBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;

@Configuration
@EnableBatchProcessing
public class MyJob {

    @Autowired
    private JobBuilderFactory jobs;

    @Autowired
    private StepBuilderFactory steps;

    @Bean
    public FlatFileItemReader<Person> itemReader() {
        return new FlatFileItemReaderBuilder<Person>()
                .name("personItemReader")
                .resource(new ClassPathResource("persons.csv"))
                .delimited()
                .includedFields(new Integer[] {0, 2})
                .names(new String[] {"id", "lastName"})
                .targetType(Person.class)
                .build();
    }

    @Bean
    public ItemWriter<Person> itemWriter() {
        return items -> {
            for (Person item : items) {
                System.out.println("person = " + item);
            }
        };
    }

    @Bean
    public Step step() {
        return steps.get("step")
                .<Person, Person>chunk(1)
                .reader(itemReader())
                .writer(itemWriter())
                .build();
    }

    @Bean
    public Job job() {
        return jobs.get("job")
                .start(step())
                .build();
    }

    public static void main(String[] args) throws Exception {
        ApplicationContext context = new AnnotationConfigApplicationContext(MyJob.class);
        JobLauncher jobLauncher = context.getBean(JobLauncher.class);
        Job job = context.getBean(Job.class);
        jobLauncher.run(job, new JobParameters());
    }

    public static class Person {
        String id;
        String firstName;
        String lastName;
        int age;

        public Person() {
        }

        public String getId() {
            return id;
        }

        public void setId(String id) {
            this.id = id;
        }

        public String getFirstName() {
            return firstName;
        }

        public void setFirstName(String firstName) {
            this.firstName = firstName;
        }

        public String getLastName() {
            return lastName;
        }

        public void setLastName(String lastName) {
            this.lastName = lastName;
        }

        public int getAge() {
            return age;
        }

        public void setAge(int age) {
            this.age = age;
        }

        @Override
        public String toString() {
            return "Person{" +
                    "id='" + id + '\'' +
                    ", firstName='" + firstName + '\'' +
                    ", lastName='" + lastName + '\'' +
                    ", age=" + age +
                    '}';
        }
    }

}

输入文件persons.csv如下:

1,foo1,bar1,10
2,foo2,bar2,20

该示例显示了如何仅映射idlastName字段。

希望这可以帮助。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何在春季批处理中使用FlatFileItemReader忽略CSV中不需要的列

使用批处理脚本仅读取分隔文件中的特定列

如何在批处理中读取CSV文件特定列中的值?

Spring Batch:如何使用FlatFileItemReader读取CSV文件的页脚并进行验证

使用Windows批处理脚本在CSV文件中添加列

仅读取CSV文件中的特定列

如何在春季批处理中在单个项目读取器中读取逗号分隔和管道分隔的csv文件

Spring Batch:如何设置FlatFileItemReader来读取json文件?

Spring批处理IncorrectTokenCountException阅读器接受csv文件中的多列

CSV文件中的“要复制的批处理文件”列

如何读取批处理文件中的错误输出流?

如何读取txt文件中的指定行(批处理)

批处理:如何从双击的文件中读取路径?

如何从 Windows 中的批处理文件乘以 CSV 表中的列

如何使用批处理脚本跳过注释行以从文本文件中读取

如何按照使用 Windows 批处理脚本显示的顺序从文本文件中读取行?

使用批处理文件替换 csv 文件中的 (C*)

批处理:如何从csv文件中删除所有空列

使用fgets和strtok在C中读取CSV文件仅读取第一列

批处理文件以删除csv中的列

使用批处理脚本,如何使用正则表达式拆分 .csv 文件中的数据?

使用 .csv 文件上的批处理对同一列中的每个内容分别求和总值

如何使用 Apache Camel 读取文件,使用 Spring 批处理处理文件,读取每一行并将其路由回 Apache Camel

如何使用Pandas读取不包含标题的CSV文件,仅捕获第一列中的数据并执行删除操作?

如何使用PHP读取csv文件中的第二列?

如何使用java读取CSV文件中的特定列?

使用批处理将csv文件加载到mysql中?

从批处理脚本中读取文件

如何使用批处理文件在系统文件夹中创建批处理文件