簡體   English   中英

如何在處理大型 csv 文件時從 spring 批處理中的下一個文件開始禁用/避免 linesToSkp(1)

[英]How to disable/avoid linesToSkp(1) from next file onwards in spring batch while processing large csv file

我們有 csv 大文件,有 1 億條記錄,並使用 spring 批處理加載、讀取和寫入數據庫,方法是使用“SystemCommandTasklet”拆分具有 100 萬條記錄的文件。 下面是片段,

 @Bean
@StepScope
public SystemCommandTasklet splitFileTasklet(@Value("#{jobParameters[filePath]}") final String inputFilePath) {
    SystemCommandTasklet tasklet = new SystemCommandTasklet();

    final File file = BatchUtilities.prefixFile(inputFilePath, AppConstants.PROCESSING_PREFIX);

    final String command = configProperties.getBatch().getDataLoadPrep().getSplitCommand() + " " + file.getAbsolutePath() + " " + configProperties.getBatch().getDataLoad().getInputLocation() + System.currentTimeMillis() / 1000;
    tasklet.setCommand(command);
    tasklet.setTimeout(configProperties.getBatch().getDataLoadPrep().getSplitCommandTimeout());

    executionContext.put(AppConstants.FILE_PATH_PARAM, file.getPath());

    return tasklet;
}

和批處理配置:

batch:
  data-load-prep:
    input-location: /mnt/mlr/prep/
    split-command: split -l 1000000 --additional-suffix=.csv       
    split-command-timeout: 900000 # 15 min
    schedule: "*/60 * * * * *"
    lock-at-most: 5m

通過以上配置,我可以讀取負載並成功寫入數據庫。 但是,發現以下代碼片段存在一個錯誤,即在拆分文件后,只有第一個文件會有標題,但下一個拆分文件的第一行沒有聽眾。 因此,我必須禁用或避免 FlatFileItemReader(CSVReader) 的 linesToSkip(1) 配置。

    @Configuration
public class DataLoadReader {

    @Bean
    @StepScope
    public FlatFileItemReader<DemographicData> demographicDataCSVReader(@Value("#{jobExecutionContext[filePath]}") final String filePath) {
        return new FlatFileItemReaderBuilder<DemographicData>()
                .name("data-load-csv-reader")
                .resource(new FileSystemResource(filePath))
                .linesToSkip(1) // Need to avoid this from 2nd splitted file onwards as splitted file does not have headers
                .lineMapper(lineMapper())
                .build();
    }

    public LineMapper<DemographicData> lineMapper() {
        DefaultLineMapper<DemographicData> defaultLineMapper = new DefaultLineMapper<>();
        DelimitedLineTokenizer lineTokenizer = new DelimitedLineTokenizer();

        lineTokenizer.setNames("id", "mdl65DecileNum", "mdl66DecileNum", "hhId", "dob", "firstName", "middleName",
                "lastName", "addressLine1", "addressLine2", "cityName", "stdCode", "zipCode", "zipp4Code", "fipsCntyCd",
                "fipsStCd", "langName", "regionName", "fipsCntyName", "estimatedIncome");

        defaultLineMapper.setLineTokenizer(lineTokenizer);
        defaultLineMapper.setFieldSetMapper(new DemographicDataFieldSetMapper());
        return defaultLineMapper;
    }
}

注意:加載程序在加載時不應跳過第二個文件的第一行。

先感謝您。 感謝任何建議。

我將使用以下命令在SystemCommandTasklet中執行此操作:

tail -n +2 data.csv | split -l 1000000 --additional-suffix=.csv

如果你真的想在你的 Spring 批處理作業中使用 Java 來完成它,你可以使用自定義閱讀器或過濾 header 的項目處理器。但我推薦這種方法,因為它為每個項目引入了額外的測試(考慮到大輸入文件中的行數,這可能會影響工作的性能)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM