이번 글에서는 csv 파일을 읽어 다른 형태로 작업 후 txt 파일로 쓰는 방법에 대해 알아보겠습니다.
먼저 FileReadWriteConfig 클래스를 만들고 의존관계를 주입합니다.
@Configuration
@RequiredArgsConstructor
public class FileReadWriteConfig {
private final JobBuilderFactory jobBuilderFactory;
private final StepBuilderFactory stepBuilderFactory;
}
그리고 이번에 읽어들일 csv 파일을 보면 가장 첫줄이 컬럼명이고 그 아래부터는 컬럼의 데이터입니다.
ID,lastName,firstName,position,birthYear,debutYear
AbduKa00,Abdul-Jabbar,Karim,rb,1974,1996
AbduRa00,Abdullah,Rabih,rb,1975,1999
AberWa00,Abercrombie,Walter,rb,1959,1982
AbraDa00,Abramowicz,Danny,wr,1945,1967
AdamBo00,Adams,Bob,te,1946,1969
AdamCh00,Adams,Charlie,wr,1979,2003
그런 다음 FlatFileItemReader와 ItemProcessor 그리고 FlatFileItemWriter 세 객체를 매서드를 통해 만들어보겠습니다. 먼저 이번의 경우 읽어야 할 대상이 파일이기 때문에 ItemReader의 자손인 FlatFileItemReader를 이용합니다.
// 리더
@Bean
@StepScope
public FlatFileItemReader<Player> playerFlatFileItemReader() {
return new FlatFileItemReaderBuilder<>()
.name("playerFlatFileItemReader")
.resource(new FileSystemResource("players.csv"))
.lineTokenizer(new DelimitedLineTokenizer())
.fieldSetMapper(new PlayerFieldSetMapper())
.linesToSkip(1)
.build();
}
중간에 보이는 이 코드는 별도로 csv 파일에서 읽은 데이터를 전달하지 않아도 csv에서 읽은 한 줄의 데이터를 하나의 객체로 만드는 기능을 합니다.
.fieldSetMapper((FieldSetMapper)new PlayerFieldSetMapper())
PlayerFieldSetMapper 클래스는 아래와 같습니다.
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;
}
}
그리고 ItemProcessor에서는 ItemReader를 통해 받은 Player 객체를 PlayerYears 객체로 변환합니다.
// 프로세서
@Bean
@StepScope
public ItemProcessor<Player, PlayerYears> playerPlayerYearsItemProcessor() {
return new ItemProcessor<Player, PlayerYears>() {
@Override
public PlayerYears process(Player item) throws Exception {
return new PlayerYears(item);
}
};
}
마지막으로 파일을 쓰는 FlatFileItemWriter에서는 처리한 데이터로 txt 파일을 만듭니다.
// 라이터
@Bean
@StepScope
public FlatFileItemWriter<PlayerYears> playerYearsItemWriter() {
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("player_output.txt");
return new FlatFileItemWriterBuilder<PlayerYears>()
.name("playerYearsItemWriter")
.resource(outputResource)
.lineAggregator(lineAggregator)
.build();
}
결과물은 이렇습니다.
AbduKa00,Abdul-Jabbar,rb,27
AbduRa00,Abdullah,rb,24
AberWa00,Abercrombie,rb,41
AbraDa00,Abramowicz,wr,56
AdamBo00,Adams,te,54
AdamCh00,Adams,wr,20
다음 글에서는 2개 이상의 Step을 등록하는 방법과 스텝 간의 분기처리하는 방법에 대해 알아보겠습니다.