-
12. ItemReader (File)BackEnd/Spring Batch 2021. 12. 30. 21:45반응형
FlatFileItemReader
2차원 데이터(표)로 표현된 유형의 파일을 처리하는 ItemReader입니다. 일반적으로 고정 위치로 정의된 데이터 필드(FixedLengthTokenizer)나 특수 문자에 의해 구별된 데이터의 행(DelimitedLineTokenizer)을 읽습니다. Resource와 LineMapper 두 가지 요소가 필요합니다.
Resource
- FileSystemResource: new FileSystemResource("resource/path/config.xml")
- ClassPathResource: new ClassPathResource("classpath:path/config.xml")
LineMapper
파일의 라인 한 줄을 Object로 변환해서 FlatFileItemReader로 리턴합니다. 단순히 문자열을 받기 때문에 문자열을 토큰화해서 객체로 매핑하는 과정이 필요하며, LineTokenizer와 FieldSetMapper를 사용해서 처리합니다.
LineTokenizer
입력받은 라인을 FieldSet으로 변환해서 리턴합니다. 파일마다 형식이 다르기 때문에 문자열을 FieldSet으로 변환하는 작업을 추상화시켜야 합니다.
FieldSet
라인을 필드로 구분해서 만든 배열 토큰을 전달하면 토큰 필드를 참조할 수 있도록 합니다. JDBC의 ResultSet과 유사합니다.
FieldSetMapper
FieldSet 객체를 받아서 원하는 객체로 매핑해서 리턴합니다. JdbcTemplate의 RowMapper와 동일한 패턴을 사용합니다.
API
DelimitedLineTokenizer
한 개 라인의 String을 구분자 기준으로 나누어 토큰화 하는 방식입니다. (default: ",")
public FlatFileItemReader itemReader() { return new FlatFileItemReaderBuilder<Customer>() .name("flatFile") .resource(new ClassPathResource("customer.csv")) .fieldSetMapper(new BeanWrapperFieldSetMapper<>()) .targetType(Customer.class) .linesToSkip(1) .delimited().delimiter(",") .names("name","year","age") .build(); }
FixedLengthTokenizer
한 개 라인의 String을 사용자가 설정한 고정길이 기준으로 나누어 토큰화 하는 방식입니다. 범위는 문자열 형식으로 설정할 수 있으며, 마지막 범위가 열려 있으면 나머지 행이 해당 열로 읽혀집니다. 예) "1-4" 또는 "1-3,4-6,7"
package io.springbatch.springbatchlecture; import lombok.Data; @Data public class Customer { private String name; private String year; private int age; }
package io.springbatch.springbatchlecture; import lombok.RequiredArgsConstructor; import org.springframework.batch.core.*; import org.springframework.batch.core.configuration.annotation.JobBuilderFactory; import org.springframework.batch.core.configuration.annotation.StepBuilderFactory; import org.springframework.batch.item.ItemWriter; import org.springframework.batch.item.file.FlatFileItemReader; import org.springframework.batch.item.file.builder.FlatFileItemReaderBuilder; import org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper; import org.springframework.batch.item.file.transform.Range; import org.springframework.batch.repeat.RepeatStatus; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.FileSystemResource; import java.util.List; @RequiredArgsConstructor @Configuration public class FlatFilesFixedLengthConfiguration { private final JobBuilderFactory jobBuilderFactory; private final StepBuilderFactory stepBuilderFactory; @Bean public Job job() { return jobBuilderFactory.get("batchJob") .start(step1()) .next(step2()) .build(); } @Bean public Step step1() { return stepBuilderFactory.get("step1") .<String, String>chunk(3) .reader(itemReader()) .writer(new ItemWriter() { @Override public void write(List items) throws Exception { items.forEach(item -> System.out.println(item)); } }) .build(); } public FlatFileItemReader itemReader() { return new FlatFileItemReaderBuilder<Customer>() .name("flatFile") .resource(new FileSystemResource("C:\\lecture\\src\\main\\resources\\customer.txt")) .fieldSetMapper(new BeanWrapperFieldSetMapper<>()) .targetType(Customer.class) .linesToSkip(1) .fixedLength() .addColumns(new Range(1,5)) .addColumns(new Range(6,9)) .addColumns(new Range(10,11)) /*.addColumns(new Range(1)) .addColumns(new Range(6)) .addColumns(new Range(10))*/ .names("name","year","age") .build(); } @Bean public Step step2() { return stepBuilderFactory.get("step2") .tasklet((contribution, chunkContext) -> { System.out.println("step2 has executed"); return RepeatStatus.FINISHED; }) .build(); } }
Exception Handling
라인을 읽거나 토큰화 할 때 발생하는 Parsing 예외를 처리할 수 있도록 예외 계층을 제공합니다. 토큰화 검증을 엄격하게 적용하지 않도록 설정하면 Parsing 예외가 발생하지 않도록 할 수 있습니다.
LineTokenizer의 Strict 속성을 false로 설정하게 되면 Tokenizer가 라인 길이를 검증하지 않습니다. FieldSet은 성공적으로 리턴이 되며 범위가 없을 경우 빈 토큰을 가지게 됩니다.
public FlatFileItemReader itemReader() { return new FlatFileItemReaderBuilder<Customer>() .name("flatFile") .resource(new ClassPathResource("customer.txt")) .fieldSetMapper(new BeanWrapperFieldSetMapper<>()) .targetType(Customer.class) .linesToSkip(1) .fixedLength() .strict(false) .addColumns(new Range(1,5)) .addColumns(new Range(6,9)) .addColumns(new Range(10,11)) .names("name","year","age") .build(); }
[참고자료]
반응형'BackEnd > Spring Batch' 카테고리의 다른 글
14. ItemReader (Json) (0) 2021.12.30 13. ItemReader (XML) (0) 2021.12.30 11. 스프링 배치 청크 프로세스 (Chunk) (0) 2021.12.24 10. Scope (0) 2021.12.24 09. Flow (0) 2021.12.23