2012-08-09 5 views
1

필자는이 코드를 매우 자주 작업하고 있으며 막 다른 방향으로 라우팅하는 경우 단순한 헤드를주고 싶습니다. 이제 im은 다른 .csv 파일에서 동일한 셀을 mathch하고 한 행을 다른 CSV 파일로 복사하는 지점입니다. 문제는 실제로 specfic 라인에서 쓰는 것이 가능할 것입니다. 예를 들어 2 셀이 50 행에 일치하면 50 행에 다시 쓰고 싶습니다. 나는 아마 hashmap에 모든 것을 추출 할 것이라고 가정하고 있습니다. 그런 다음 .csv 파일에 다시 씁니다. 더 쉬운 방법이 있습니까?슈퍼 csv를 사용하여 Java로 csv에 다시 작성

예를 들어 사람 세부 정보가있는 하나의 CSV가 있고 다른 하나에는 실제 사람이 살고있는 곳의 속성 세부 정보가 있습니다. 나는 속성 정보를 사람 CSV로 복사하고 정확한 사람 세부 정보와 일치 시키려합니다. . 다음과 같은 상황이처럼이 당신의 코멘트에서 의미

public class Old { 
public static void main(String [] args) throws IOException 
{ 
    List<String[]> cols; 
    List<String[]> cols1; 

    int row =0; 
    int count= 0; 
    boolean b; 
    CsvMapReader Reader = new CsvMapReader(new FileReader("file1.csv"), CsvPreference.EXCEL_PREFERENCE); 
    CsvMapReader Reader2 = new CsvMapReader(new FileReader("file2.csv"), CsvPreference.EXCEL_PREFERENCE); 

    try { 
     cols = readFile("file1.csv"); 
     cols1 = readFile("fiel2.csv"); 
     String [] headers = Reader.getCSVHeader(true); 

     headers = header(cols1,headers   

      } catch (IOException e) { 
     e.printStackTrace(); 
     return; 
    } 

    for (int j =1; j<cols.size();j++) //1 
    { 
     for (int i=1;i<cols1.size();i++){ 
      if (cols.get(j)[0].equals(cols1.get(i)[0])) 
      { 


      } 
     } 

    } 

} 


private static List<String[]> readFile(String fileName) throws IOException 
{ 
    List<String[]> values = new ArrayList<String[]>(); 
    Scanner s = new Scanner(new File(fileName)); 
    while (s.hasNextLine()) { 
     String line = s.nextLine(); 
     values.add(line.split(",")); 
    } 
    return values; 
} 
public static void csvWriter (String fileName, String [] nameMapping) throws FileNotFoundException 
{ 
    ICsvListWriter writer = new CsvListWriter(new PrintWriter(fileName),CsvPreference.STANDARD_PREFERENCE); 
    try { 
     writer.writeHeader(nameMapping); 

    } catch (IOException e) { 

     e.printStackTrace(); 
    } 

} 
public static String[] header(List<String[]> cols1, String[] headers){ 
    List<String> list = new ArrayList<String>(); 
    String [] add; 
    int count= 0; 
    for (int i=0;i<headers.length;i++){ 
     list.add(headers[i]); 
    } 

    boolean c; 
    c= true; 
    while(c)  {   
     add = cols1.get(0); 
     list.add(add[count]); 
     if (cols1.get(0)[count].equals(null))// this line is never read errpr 
     {    
      c=false; 
      break; 
     } else 
     count ++; 

    } 

    String[] array = new String[list.size()]; 
    list.toArray(array); 
    return array; 

} 
+0

난 당신이 예를 줄 수, 당신이 달성하고자하는 것을 이해 확실하지 않다? – Thomas

+0

예를 들어 사람 세부 정보가있는 Csv가 하나 있고 다른 사람에게는 실제 사람이 살고있는 곳의 속성 세부 정보가 있습니다. 속성 세부 정보를 사람 CSV에 복사하고 올바른 사람 세부 정보와 일치 시키려합니다. 이것이 의미가되기를 바랍니다. @Thomas –

+0

FYI [Super CSV 2.0.0-beta-1] (http://supercsv.sourceforge.net/release_notes.html)이 출시되었습니다. 여기에는 많은 버그 수정과 새로운 기능 (Maven 지원 및 중첩 된 속성 및 배열/컬렉션 매핑을위한 새로운 Dozer 확장 기능 포함)이 포함되어 있습니다. –

답변

1

토마스가 제안한대로 모든 주소와 사람 세부 정보를 먼저 읽으면주의해야합니다. 작은 CSV 파일 만 다루는 경우에는 문제가 없지만 메모리가 부족할 수 있습니다. 더 큰 파일을 다루고 있습니다.

다른 방법으로, 먼저 주소를 읽은 다음 사람 세부 정보를 읽는 동안 결합 ​​된 사람/주소 정보를 작성하는 예제를 작성했습니다.

그냥 몇 가지 참고 사항 :

당신이 있었기 때문에 내가 CsvMapReader 및 CsvMapWriter을 사용했습니다
  • -이 내가 주소를 저장하는지도를 포함하는지도를 사용 했어 의미했다. CsvBeanReader/CsvBeanWriter를 사용하면 좀 더 우아 해집니다.

  • 질문의 코드는 실제로 수퍼 CSV를 사용하여 CSV (ScannerString.split())를 읽지 않습니다. CSV에 데이터에 쉼표가 포함되어 있으면 (주소로도 가능) 문제가 발생할 수 있으므로 이스케이프 처리 된 쉼표를 처리하는 Super CSV를 사용하는 것이 훨씬 안전합니다.

예 :

package example; 

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

import org.supercsv.io.CsvMapReader; 
import org.supercsv.io.CsvMapWriter; 
import org.supercsv.io.ICsvMapReader; 
import org.supercsv.io.ICsvMapWriter; 
import org.supercsv.prefs.CsvPreference; 

public class CombiningPersonAndAddress { 

    private static final String PERSON_CSV = "id,firstName,lastName\n" 
      + "1,philip,fry\n2,amy,wong\n3,hubert,farnsworth"; 

    private static final String ADDRESS_CSV = "personId,address,country\n" 
      + "1,address 1,USA\n2,address 2,UK\n3,address 3,AUS"; 

    private static final String[] COMBINED_HEADER = new String[] { "id", 
      "firstName", "lastName", "address", "country" }; 

    public static void main(String[] args) throws Exception { 

     ICsvMapReader personReader = null; 
     ICsvMapReader addressReader = null; 
     ICsvMapWriter combinedWriter = null; 
     final StringWriter output = new StringWriter(); 

     try { 
      // set up the readers/writer 
      personReader = new CsvMapReader(new StringReader(PERSON_CSV), 
        CsvPreference.STANDARD_PREFERENCE); 
      addressReader = new CsvMapReader(new StringReader(ADDRESS_CSV), 
        CsvPreference.STANDARD_PREFERENCE); 
      combinedWriter = new CsvMapWriter(output, 
        CsvPreference.STANDARD_PREFERENCE); 

      // map of personId -> address (inner map is address details) 
      final Map<String, Map<String, String>> addresses = 
        new HashMap<String, Map<String, String>>(); 

      // read in all of the addresses 
      Map<String, String> address; 
      final String[] addressHeader = addressReader.getCSVHeader(true); 
      while ((address = addressReader.read(addressHeader)) != null) { 
       final String personId = address.get("personId"); 
       addresses.put(personId, address); 
      } 

      // write the header 
      combinedWriter.writeHeader(COMBINED_HEADER); 

      // read each person 
      Map<String, String> person; 
      final String[] personHeader = personReader.getCSVHeader(true); 
      while ((person = personReader.read(personHeader)) != null) { 

       // copy address details to person if they exist 
       final String personId = person.get("id"); 
       final Map<String, String> personAddress = addresses.get(personId); 
       if (personAddress != null) { 
        person.putAll(personAddress); 
       } 

       // write the combined details 
       combinedWriter.write(person, COMBINED_HEADER); 
      } 

     } finally { 
      personReader.close(); 
      addressReader.close(); 
      combinedWriter.close(); 
     } 

     // print the output 
     System.out.println(output); 

    } 
} 

출력 :

id,firstName,lastName,address,country 
1,philip,fry,address 1,USA 
2,amy,wong,address 2,UK 
3,hubert,farnsworth,address 3,AUS 
+0

아이디어를 주셔서 감사합니다 대단히 감사합니다, 내 while 루프 문제. @Hound Dog는 java.lang.nullPointer 예외를 반환합니다. 나는 그것을 깨뜨렸고 90 번 행에서 멈추는 것처럼 보인다. –

+0

@jbel 나는 당신이 당신의 원래 코드에 대해 이야기하고 있다고 생각한다. 내 생각 엔'cols1.get (0) [count] .equals (null)'에서 발생하는 것입니다. 배열의 요소가 null이면'.equals() '가 null이기 때문에 어떤 것이 null인지 확인하는 올바른 방법이 아닙니다. 'NullPointerException을 발생시킵니다. 그것은'cols1.get (0) [count] == ​​null'이어야합니다. 그 말은, 당신이 코드를 내 예제처럼 보이게하는 것이 더 낫다는 것입니다 - 거기에 읽기/중복 코드가 많이 있습니다! –

+0

귀하의 코드를 사용하여, 내 appoligies 당신이 [code] combinedWriter.write (person, COMBINED_HEADER); @/Hound Dog. 메신저가이 사용자의 오류라고 가정합니다. –

1

을 만드는 희망이 보인다 : 1 명을 포함

  • 파일을
  • 파일이 포함 된 주소

그런 다음 원하는 일부 키 (하나 이상의 필드)로 사람과 주소를 일치시키고 조합을 CSV 파일에 다시 작성합니다.

//use a LinkedHashMap to preserve the order of the persons as found in file 1 
Map<PersonKey, String[]> persons = new LinkedHashMap<>(); 
//fill in the persons from file 1 here 

Map<PersonKey, String[]> addresses = new HashMap<>(); 
//fill in the addresses from file 2 here 

List<String[]> outputLines = new ArrayList<>(persons.size());  
for(Map.Entry<PersonKey, String[]> personEntry: persons.entrySet()) { 
    String[] person = personEntry.getValue(); 
    String[] address = addresses.get(personEntry.getKey()); 

    //merge the two arrays and put them into outputLines 
} 

//write outputLines to a file 

PersonKey 그건 그냥 할 수있는 String 또는 래퍼 객체 (Integer 등)가 하나 개의 필드에 의해 사람과 주소를 일치시킬 수있는 경우 :

따라서 가장 간단한 방법은 다음과 같이 될 수 있습니다. 필드가 더 많은 경우 맞춤 PersonKey 개체가 equals()이고 hashCode()이 적절히 재정의되어야 할 수 있습니다.

관련 문제