2017-11-27 1 views
0

원시 CSV는 다음과 같이이다 :Spring Batch를 사용하여 하나의 셀에 복수 라인이 포함 된 CSV 파일을 읽는 방법?

첫 번째 줄 :

Name, StudentId, Comment 
    Jake, 12312, poor 
    Emma, 12324, good 
    Mary, 13214, need more work on programming 
       and math. 

csv로 데이터의 마지막 항목의 주석 셀은 두 줄을 포함 : 이름, StudentID는,

데이터를 주석 처리합니다. 나는 그것을 하나의 라인 데이터로 취급하고 싶다.

flatItemReader를 사용하여 파일을 읽을 때 "예상 토큰 3이지만 실제 1"에 대한 오류가 발생합니다. 두 번째 줄을 새 줄로 처리한다고 생각합니다. 한 줄로 처리 할 수있는 방법이 있습니까?

답변

0

독자가 구분 기호로 분리하지 않고 각 줄에 원시 문자열을 반환하게하십시오. 구문 분석을 처리 할 프로세서를 만듭니다 (상태 유지가 필요함). 유일한 까다로운 부분은 어떻게 든 EOF에 도달했을 때 프로세서에 신호를 보내야하므로 다음 줄을 집계해야하는지 기다릴 필요가 없다는 것입니다. 이런 식으로 뭔가 :

public class AggregatingItemProcessor<T> implements ItemProcessor<T, T>, InitializingBean { 

    private BiPredicate<T, T> aggregatePredicate; 
    private BiFunction<T, T, T> aggregator; 

    public void setAggregatePredicate(BiPredicate<T, T> aggregatePredicate) { 
     this.aggregatePredicate = aggregatePredicate; 
    } 

    public void setAggregator(BiFunction<T, T, T> aggregator) { 
     this.aggregator = aggregator; 
    } 

    private T cur; 

    @Override 
    public T process(T item) throws Exception { 
     if(cur == null) { 
      cur = item; 
      return null; 
     } 
     if(aggregatePredicate.test(cur, item)) { 
      cur = aggregator.apply(cur, item); 
      return null; 
     } else { 
      T toRet = cur; 
      cur = item; 
      return toRet; 
     } 
    } 

    @Override 
    public void afterPropertiesSet() throws Exception { 
     Assert.notNull(aggregatePredicate, "Predicate to determine if records should be aggregated must not be null."); 
     Assert.notNull(aggregator, "Function for aggregating items must not be null."); 
    } 
} 

그런 다음 설정 ...

static final String EOF_MARKER = "\0"; 

@Bean 
public FlatFileItemReader<String> reader() { 
    final FlatFileItemReader<String> reader = new FlatFileItemReader<String>() { 

     private boolean finished = false; 

     @Override 
     public String read() throws Exception, UnexpectedInputException, ParseException { 
      if(finished) return null; 
      String next = super.read(); 
      if(next == null) { 
       finished = true; 
       return EOF_MARKER; 
      } 
      return next; 
     } 

    }; 
    reader.setLineMapper((s, i) -> s); 
    return reader; 
} 

@Bean 
public AggregatingItemProcessor<String> processor() { 
    final AggregatingItemProcessor<String> processor = new AggregatingItemProcessor<>(); 
    processor.setAggregatePredicate((s1, s2) -> !EOF_MARKER.equals(s2) && StringUtils.countOccurrencesOf(s2, ",") < 2); 
    processor.setAggregator(String::concat); 
    return processor; 
} 
관련 문제