[스프링배치] 파일 읽고 쓰기

hoyong.eom·2024년 1월 24일

스프링배치

목록 보기
4/12
post-thumbnail

파일 읽고, 쓰기

스프링 배치에서 파일을 읽고 처리하고 다시 파일에 쓰는 작업을 수행하기 위한 예시코드이다.

@RequiredArgsConstructor
@Configuration
public class FileDataReadWriteConfig {


    @Autowired
    private JobBuilderFactory jobBuilderFactory;

    @Autowired
    private StepBuilderFactory stepBuilderFactory;

    @Bean
    public Job fileReadWriteJob(Step fileReadWriteStep) {
        jobBuilderFactory.get("fileReadWriteJob")
                .incrementer(new RunIdIncrementer())
                .start(fileReadWriteStep)
                .build();
    }

    @Bean
    @JobScope
    public Step fileReadWriteStep(ItemReader playerItemReader,
                                  ItemProcessor playerItemProcessor,
                                  ItemWriter playerItemWriter
                                  ) {

        return stepBuilderFactory.get("fileReadWriteStep")
                .<Player, PlayerYears>chunk(5)
                .reader(playerItemReader)
                .processor(playerItemProcessor)
                .writer(playerItemWriter)
                .build();
    }

    @StepScope
    @Bean
    public ItemProcessor<Player, PlayerYears> playerItemProcessor() {
        return new ItemProcessor<Player, PlayerYears>() {
            @Override
            public PlayerYears process(Player item) throws Exception {
                return new PlayerYears(item);
            }
        };
    }

    @StepScope
    @Bean
    public FlatFileItemReader<Player> playerItemReader() {
        return new FlatFileItemReaderBuilder<Player>()
                .name("playerItemReader")
                .resource(new FileSystemResource("Players.csv"))
                .lineTokenizer(new DelimitedLineTokenizer())
                .fieldSetMapper(new PlayerFieldSetMapper())
                .linesToSkip(1)
                .build();
    }

    @StepScope
    @Bean
    public FlatFileItemWriter<PlayerYears> playerItemWriter() {
        BeanWrapperFieldExtractor<PlayerYears> fieldExtractor = new BeanWrapperFieldExtractor<>();
        fieldExtractor.setNames(new String[]{"ID", "lastName", "position", "yearsExperience"});
        fieldExtractor.afterPropertiesSet();

        DelimitedLineAggregator<PlayerYears> lineAggregator = new DelimitedLineAggregator<>();
        lineAggregator.setDelimiter("=");
        lineAggregator.setFieldExtractor(fieldExtractor);

        FileSystemResource outputResource = new FileSystemResource("players_output.txt");

        return new FlatFileItemWriterBuilder<PlayerYears>()
                .name("playerItemWriter")
                .resource(outputResource)
                .lineAggregator(lineAggregator)
                .build();
    }
}

소스 코드의 핵심 내용을 살펴보자!

.<Player, PlayerYears>chunk(5)

이전 포스팅에서 공부했던것 처럼 Player를 PlayerYears 객체로 트랜잭션을 5개의 단위로 커밋합니다.

public ItemProcessor<Player, PlayerYears> playerItemProcessor()

ItemProcessor는 Player를 PlayerYears로 변환하는 후처리 역할을 수행합니다.

FlatFileItemReader

FlatFileItemReader는 ItemReader의 일종으로서 파일에서 읽어온 데이터를 Player 객체에 담아주는 역할을 수행합니다.

  return new FlatFileItemReaderBuilder<Player>()
                .name("playerItemReader")
                .resource(new FileSystemResource("Players.csv"))
                .lineTokenizer(new DelimitedLineTokenizer())
                .fieldSetMapper(new PlayerFieldSetMapper())
                .linesToSkip(1)
                .build();
  • .name("playerItemReader") : ItemReader의 이름을 지정합니다.
  • .resource(new FileSystemResource("Players.csv")) : 읽어올 파일을 지정합니다.
  • .lineTokenizer(new DelimitedLineTokenizer()) : 파일을 콤마 단위로 읽어도록 Tokenzier를 지정합니다.
  • .fieldSetMapper(new PlayerFieldSetMapper()) : 파일에서 읽어온 값을 Player 객체에 맵핑합니다.
public class PlayerFieldSetMapper implements FieldSetMapper<Player> {
    public Player mapFieldSet(FieldSet fieldSet) {
        Player player = new Player();

        player.setID(fieldSet.readString(0));
        player.setLastName(fieldSet.readString(1));
        player.setFirstName(fieldSet.readString(2));
        player.setPosition(fieldSet.readString(3));
        player.setBirthYear(fieldSet.readInt(4));
        player.setDebutYear(fieldSet.readInt(5));

        return player;
    }
}
  • .linesToSkip(1) : 파일의 헤더는 제목이기 때문에 생략합니다.

FlatFileItemWriter

FlatFileItemReader와 유사하게 PlayerYears 객체를 파일에 쓰는 역할을 구현합니다.

    @StepScope
    @Bean
    public FlatFileItemWriter<PlayerYears> playerItemWriter() {
        BeanWrapperFieldExtractor<PlayerYears> fieldExtractor = new BeanWrapperFieldExtractor<>();
        fieldExtractor.setNames(new String[]{"ID", "lastName", "position", "yearsExperience"});
        fieldExtractor.afterPropertiesSet();

        DelimitedLineAggregator<PlayerYears> lineAggregator = new DelimitedLineAggregator<>();
        lineAggregator.setDelimiter("=");
        lineAggregator.setFieldExtractor(fieldExtractor);

        FileSystemResource outputResource = new FileSystemResource("players_output.txt");

        return new FlatFileItemWriterBuilder<PlayerYears>()
                .name("playerItemWriter")
                .resource(outputResource)
                .lineAggregator(lineAggregator)
                .build();
    }
  • BeanWrapperFieldExtractor : 객체에서 추출할 속성을 명시합니다.
  • DelimitedLineAggregator : 새롭게 생성할 파일이 어떤 기준으로 만들어질지를 명시하기 위해 딜리미터를 명시해준다.
  • FileSystemResource outputResource : 생성할 파일을 지정한다.

0개의 댓글