使用Spring Batch

时间:2015-11-18 10:30:08

标签: spring spring-batch

我需要解析给定文件夹中的几个csv文件。由于每个csv具有不同的列,因此每个csv在DB中都有单独的表。我需要知道

  • Spring批处理是否提供了扫描给定文件夹的任何机制,然后我可以将这些文件逐个传递给阅读器。
  • 当我试图使读/写器具有通用性时,是否有可能只为每个csv获取列标题,基于我正在尝试构建tokenizer以及插入查询。

代码示例

public ItemReader<Gdp> reader1() {
    FlatFileItemReader<Gdp> reader1 = new FlatFileItemReader<Gdp>();
    reader1.setResource(new ClassPathResource("datagdp.csv"));
    reader1.setLinesToSkip(1);
    reader1.setLineMapper(new DefaultLineMapper<Gdp>() {
        {
            setLineTokenizer(new DelimitedLineTokenizer() {
                {
                    setNames(new String[] { "region", "gdpExpend", "value" });
                }
            });
            setFieldSetMapper(new BeanWrapperFieldSetMapper<Gdp>() {
                {
                    setTargetType(Gdp.class);
                }
            });
        }
    });
    return reader1;
}

3 个答案:

答案 0 :(得分:4)

使用MultiResourceItemReader扫描所有文件 我认为你需要一种分类的ItemReader作为MultiResourceItemReader.delegate但是SB没有提供,所以你必须自己编写。
对于ItemProcessorItemWriter,SB提供了一个分类器感知的实现(ClassifierCompositeItemProcessorClassifierCompositeItemWriter)。
显然,更多不同的输入文件你必须写更多的XML配置,但它应该是直截了当的。

答案 1 :(得分:0)

我想您期望这种实现。

  1. 在“分区步骤生成器”期间,读取所有文件名,文件头,为编写器插入查询,并将其保存在执行上下文中。

  2. 在从属步骤中,对于每个读取器和写入器,传递Execution上下文,获取要读取的文件,将文件头传递给令牌生成器,插入需要为该写入器插入的查询。

这可以解决您的问题。

答案 2 :(得分:-1)

您的问题的答案:

  1. 我不知道春季批量扫描文件的具体机制。
  2. 您可以使用opencsv作为通用CSV阅读器,有很多机制可以读取文件。
  3. 关于OpenCSV: 如果您正在使用maven项目,请尝试导入此依赖项:

     <dependency> 
       <groupId>net.sf.opencsv</groupId> 
       <artifactId>opencsv</artifactId> 
        <version>2.0</version> 
     </dependency> 
    

    您可以阅读为特定格式制作对象的文件,或如下所示的通用标题:

    private static List<DadosPeople> extrairDadosPeople() throws IOException {
        CSVReader readerPeople = new CSVReader(new FileReader(people));
        List<PeopleData> listPeople = new ArrayList<PeopleData>();
        String[] nextLine;
        while ((nextLine = readerPeople.readNext()) != null) {
            PeopleData people = new PeopleData();
            people.setIncludeData(nextLine[0]);
            people.setPartnerCode(Long.valueOf(nextLine[1]));
    
            listPeople.add(people);
        }
        readerPeople.close();
        return listPeople;
    }
    

    还有很多其他方法可以使用opencsv读取CSV文件:

    如果要使用Iterator样式模式,可以执行以下操作:

     CSVReader reader = new CSVReader(new FileReader("yourfile.csv"));
     String [] nextLine;
     while ((nextLine = reader.readNext()) != null) {
        // nextLine[] is an array of values from the line
        System.out.println(nextLine[0] + nextLine[1] + "etc...");
     }
    

    或者,如果您可能只想将整个数据放入List中,只需调用readAll()......

     CSVReader reader = new CSVReader(new FileReader("yourfile.csv"));
     List myEntries = reader.readAll();
    

    将为您提供可以迭代的String []列表。如果所有其他方法都失败了,请在这里查看Javadocs。 如果要自定义引号字符和分隔符,您将找到适合提供自己的分隔符和引号字符的构造函数。假设您正在使用分隔符的标签,您可以执行以下操作:

     CSVReader reader = new CSVReader(new FileReader("yourfile.csv"), '\t');
    

    如果您单独引用转义字符而不是双引号,则可以使用三个arg构造函数:

     CSVReader reader = new CSVReader(new FileReader("yourfile.csv"), '\t', '\'');
    

    如果您知道内容在文件中稍后才开始播放,您也可以跳过文件的前几行。因此,例如,您可以通过执行以下操作跳过前两行:

     CSVReader reader = new CSVReader(new FileReader("yourfile.csv"), '\t', '\'', 2);
    

    我可以用opencsv编写csv文件吗?

    是。在同一个包中有一个CSVWriter,它遵循与CSVReader相同的语义。例如,要编写制表符分隔文件:

     CSVWriter writer = new CSVWriter(new FileWriter("yourfile.csv"), '\t');
     // feed in your array (or convert your data to an array)
     String[] entries = "first#second#third".split("#");
     writer.writeNext(entries);
     writer.close();
    

    如果您更喜欢使用自己的引号字符,则可以使用构造函数的三个arg版本,它使用引号字符(或随意传入CSVWriter.NO_QUOTE_CHARACTER)。

    您还可以自定义生成的文件中使用的行终止符(当您从Linux Web应用程序导出到Windows客户端时,这很方便)。为此目的有一个构造函数参数。 我可以将SQL表转储为CSV吗?

    是的,你可以。 CSVWriter上有一个功能,因此您可以将writeAll()传递给ResultSet。

     java.sql.ResultSet myResultSet = ....
     writer.writeAll(myResultSet, includeHeaders);
    

    有没有办法将我的CSV文件绑定到Javabeans列表?

    是的。有一组类允许您根据列名,列位置或自定义映射策略将CSV文件绑定到JavaBeans列表。您可以在com.opencsv.bean包中找到新类。以下是基于CSV文件中字段位置映射到java bean的方法:

    ColumnPositionMappingStrategy strat = new ColumnPositionMappingStrategy();
    strat.setType(YourOrderBean.class);
    String[] columns = new String[] {"name", "orderNumber", "id"}; // the fields to bind do in your JavaBean
    strat.setColumnMapping(columns);
    
    CsvToBean csv = new CsvToBean();
    List list = csv.parse(strat, yourReader);