Java 如何在spring batch中的单个项目读取器中读取逗号分隔和管道分隔的csv文件

Java 如何在spring batch中的单个项目读取器中读取逗号分隔和管道分隔的csv文件,java,spring,spring-batch,batch-processing,Java,Spring,Spring Batch,Batch Processing,我是新来的小枝批。 我有一个包含多个csv文件的文件夹,我实现了MultiResourceItemReader()来读取这些文件。仅当所有csv文件以管道(“|”)分隔时,它才起作用 我想使用单个读卡器读取逗号(“,”)分隔的csv和管道分隔的csv。可能吗?如果是,怎么做 这是我的密码 @Bean @StepScope public MultiResourceItemReader<Person> multiResourceItemReader(@Value("#{jobParame

我是新来的小枝批。 我有一个包含多个csv文件的文件夹,我实现了MultiResourceItemReader()来读取这些文件。仅当所有csv文件以管道(“|”)分隔时,它才起作用

我想使用单个读卡器读取逗号(“,”)分隔的csv和管道分隔的csv。可能吗?如果是,怎么做

这是我的密码

@Bean
@StepScope
public MultiResourceItemReader<Person> multiResourceItemReader(@Value("#{jobParameters[x]}") String x,@Value("#{jobParameters[y]}") String y,@Value("#{jobParameters[z]}") String z) {

    Resource[] resourcessss = null;
    ClassLoader cl = this.getClass().getClassLoader();
    ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(cl);
    try {
        resourcessss = resolver.getResources("file:" + z);
    }catch(Exception e) {

    }
    MultiResourceItemReader<Person> resourceItemReader = new MultiResourceItemReader<Person>();
    resourceItemReader.setResources(resourcessss);
    resourceItemReader.setDelegate(reader());

    return resourceItemReader;
}



@Bean
public FlatFileItemReader<Person> reader() {
    FlatFileItemReader<Person> reader = new FlatFileItemReader<Person>();
    reader.setLineMapper(new DefaultLineMapper() {
        {
            setLineTokenizer(new DelimitedLineTokenizer() {
                {
                    setNames(new String[]{"Id","postCode"});
                }
                {
                    setDelimiter("|");
                }
            });
            setFieldSetMapper(new BeanWrapperFieldSetMapper<Person>() {
                {
                    setTargetType(Person.class);
                }
            });
        }
    });
    return reader;
}
@Bean
@步进镜
公共MultiResourceItemReader MultiResourceItemReader(@Value(“{jobParameters[x]}”)字符串x、@Value(“{jobParameters[y]}”)字符串y、@Value(“{jobParameters[z]}”)字符串z){
Resource[]resourcessss=null;
ClassLoader cl=this.getClass().getClassLoader();
ResourcePatternResolver解析器=新路径匹配ResourcePatternResolver(cl);
试一试{
resourcessss=resolver.getResources(“文件:”+z);
}捕获(例外e){
}
MultiResourceItemReader resourceItemReader=新的MultiResourceItemReader();
resourceItemReader.setResources(ResourcesSS);
setDelegate(reader());
返回resourceItemReader;
}
@豆子
公共FlatFileItemReader()读取器{
FlatFileItemReader=新的FlatFileItemReader();
reader.setLineMapper(新的DefaultLineMapper(){
{
setLineTokenizer(新的DelimitedLineTokenizer(){
{
集合名(新字符串[]{“Id”,“postCode”});
}
{
设置分隔符(“|”);
}
});
setFieldSetMapper(新的BeanRapperFieldSetMapper(){
{
setTargetType(Person.class);
}
});
}
});
返回读取器;
}

看一看
模式匹配复合物还原剂
。在这里,您可以使用
模式
来识别哪些记录被
行标记器
解析。在您的例子中,您将有一个
模式
,它标识逗号分隔的记录,并将它们映射到通过逗号解析的标记器。您还需要一个
模式
,它标识由管道分隔的记录,并将这些记录映射到相应的
行标记器
。它看起来像这样:

    @Bean
    public LineTokenizer compositeLineTokenizer() throws Exception {
        DelimitedLineTokenizer commaTokenizer = new DelimitedLineTokenizer();

        commaTokenizer.setNames("a", "b", "c");
        commaTokenizer.setDelimiter(",");
        commaTokenizer.afterPropertiesSet();

        DelimitedLineTokenizer pipeTokenizer = new DelimitedLineTokenizer();

        pipeTokenizer.setNames("a", "b", "c");
        pipeTokenizer.setDelimiter("|");

        pipeTokenizer.afterPropertiesSet();

        // I have not tested the patterns here so they may need to be adjusted
        Map<String, LineTokenizer> tokenizers = new HashMap<>(2);
        tokenizers.put("*,*", commaTokenizer);
        tokenizers.put("*|*", pipeTokenizer);

        PatternMatchingCompositeLineTokenizer lineTokenizer = new PatternMatchingCompositeLineTokenizer();

        lineTokenizer.setTokenizers(tokenizers);

        return lineTokenizer;
    }
@Bean
public LineTokenizer compositeLineTokenizer()引发异常{
DelimitedLineTokenizer commaTokenizer=新的DelimitedLineTokenizer();
集合名(“a”、“b”、“c”);
commaTokenizer.setDelimiter(“,”);
commaTokenizer.AfterPropertieSet();
DelimitedLineTokenizer pipeTokenizer=新DelimitedLineTokenizer();
集合名称(“a”、“b”、“c”);
pipeTokenizer.setDelimiter(“|”);
pipeTokenizer.AfterPropertieSet();
//我没有在这里测试模式,因此可能需要对其进行调整
映射标记器=新的HashMap(2);
tokenizer.put(“*,*”,commaTokenizer);
tokenizer.put(“*|*”,pipeTokenizer);
PatternMatchingCompositeLineTokenizer=新的PatternMatchingCompositeLineTokenizer();
lineTokenizer.setTokenizer(标记器);
返回线标记器;
}

Hi@Michael Minella。谢谢你的回复。在BatchConfig类中创建这个bean之后,我将如何将它链接到现有的reader()函数中。我需要对现有bean进行哪些更改才能使您的解决方案工作?public FlatFileItemReader(){FlatFileItemReader build=new FlatFileItemReaderBuilder().name(“fileReader”).lineTokenizer(compositeLineTokenizer()).build();return build;}您的
FlatFileItemReader
不应返回
字段集
…您应将其映射到某个对象。。。但除此之外(假设您还将添加一个
资源
),是的,它看起来是正确的;嵌套异常为java.lang.IllegalArgumentException:必须设置LineTokenizer。尝试扩展DefaultLineMapper并重写setLineTokenizer(),但没有成功,出现相同错误。您还需要配置
FieldSetMapper