2014-04-06 1 views
0

지도가있는 간단한 POJO가 있습니다.MapEntry 용 CellProcessor

public class Product { 
    public Map map; 
} 

은 내 CSV는 다음과 같습니다

"mapEntry1","mapEntry2","mapEntry3" 

그래서 내가 그 해석에 대한 사용자 정의 셀 프로세서를 만든 :

public class MapEntryCellProcessor { 
    public Object execute(Object val, CsvContext context) { 
     return next.execute(new AbstractMap.SimpleEntry<>("somekey", val), context); 
    } 
} 

을 한 후 내 제품에 엔트리 setter 메소드를 추가 :

public void setName(Entry<String, String> entry) { 
    if (getName() == null) { 
     name = new HashMap<>(); 
    } 
    name.put(entry.getKey(), entry.getValue()); 
} 

불행히도이 저 ans 나는 두 가지 setter 메소드를 가지고있다. 하나는 맵을 받아 들이고 다른 하나는 실제로 나를 위해 일하지 않는 엔트리를 받아 들인다. (나는 POJO가 어떻게 생성되는지에 대한 제어권이 없다.) 그러한 CSV를 구문 분석 할 수있는 다른 방법이 있습니까? 내 제품에서지도를 허용하는 설정자 만 있습니까?

답변

1

각 열을지도로 수집하는 셀 프로세서를 작성할 수 있습니다. 예를 들어 다음 프로세서를 사용하면 추가 할 키와 맵을 지정할 수 있습니다. 다음과 같이

package org.supercsv.example; 

import java.util.Map; 

import org.supercsv.cellprocessor.CellProcessorAdaptor; 
import org.supercsv.cellprocessor.ift.CellProcessor; 
import org.supercsv.util.CsvContext; 

public class MapCollector extends CellProcessorAdaptor { 

    private String key; 

    private Map<String, String> map; 

    public MapCollector(String key, Map<String, String> map){ 
     this.key = key; 
     this.map = map; 
    } 

    public MapCollector(String key, Map<String, String> map, 
     CellProcessor next){ 
     super(next); 
     this.key = key; 
     this.map = map; 
    } 

    public Object execute(Object value, CsvContext context) { 
     validateInputNotNull(value, context); 
     map.put(key, String.valueOf(value)); 
     return next.execute(map, context); 
    } 

} 

이 그런 다음 제품 콩 유형 Map<String,String>의 필드 name을 가지고 가정, 당신은 프로세서를 사용할 수 있습니다.

package org.supercsv.example; 

import java.io.IOException; 
import java.io.StringReader; 
import java.util.HashMap; 
import java.util.Map; 

import junit.framework.TestCase; 

import org.supercsv.cellprocessor.ift.CellProcessor; 
import org.supercsv.io.CsvBeanReader; 
import org.supercsv.io.ICsvBeanReader; 
import org.supercsv.prefs.CsvPreference; 

public class MapCollectorTest extends TestCase { 

    private static final String CSV = "John,L,Smith\n" + 
     "Sally,P,Jones"; 

    public void testMapCollector() throws IOException{ 
     ICsvBeanReader reader = new CsvBeanReader(
     new StringReader(CSV), 
      CsvPreference.STANDARD_PREFERENCE); 

     // only need to map the field once, so use nulls 
     String[] nameMapping = new String[]{"name", null, null}; 

     // create processors for each row (otherwise every bean 
     // will contain the same map!) 
     Product product; 
     while ((product = reader.read(Product.class, 
      nameMapping, createProcessors())) != null){ 
      System.out.println(product.getName()); 
     } 
    } 

    private static CellProcessor[] createProcessors() { 
     Map<String, String> nameMap = new HashMap<String, String>(); 
     final CellProcessor[] processors = new CellProcessor[]{ 
       new MapCollector("name1", nameMap), 
       new MapCollector("name2", nameMap), 
       new MapCollector("name3", nameMap)}; 
     return processors; 
    } 

} 

이 출력 :

{name3=Smith, name2=L, name1=John} 
{name3=Jones, name2=P, name1=Sally} 

당신은 프로세서가 3 열에서 실행하는 동안, 그것은 단지합니다 (nameMapping 배열에 따라서 null을) 한 번 빈에 매핑 된 것을 알 수 있습니다.) 답변에 대한

+0

감사합니다, ,

는 또한 다른 모든 콩은 아마 당신이 원하는하지 않습니다 같은지도를 ... 사용하는 것, 프로세서에게 행을 읽을 때마다 만든 내가 첫 번째 인상은 모든 행에 대한 셀 프로세서를 만드는 것은 성능을 떨어 뜨릴 것이지만 나는 그것을 시도해 보겠다. 나는 10000 개가 넘는 라인을 가진 몇몇 CSV를 가지고있다 ... –

+0

CsvContext 또한이 줄에서 지금까지 처리 된 내용과 현재 헤더 값의 이름을 노출합니다. 이 경우 다음과 같이 CsvProcessor를 만들 수 있습니다. 'if (csvContext.getLineSoFar (csvContext.getCurrentHeader())! = null) { csvContext.getLineSoFar(). put (STRING, STRING); } else { new HashMap (); } ' –