2012-08-09 52 views
1

我一直在研究這段代碼很長一段時間,只是想給予簡單的頭如果我路由下來的死衚衕。 im現在的目的是從不同的.csv文件中編制相同的單元格,並將一行復制到另一個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 2012-08-09 14:38:07

+0

例如,我有一個Csv有人的詳細信息,另一個有實際人住的地方的詳細信息,我希望將該人的詳細信息複製到人csv,並將其與正確的人物詳細信息相匹配。希望這是有道理的@Thomas – 2012-08-10 07:14:37

+0

FYI [超級CSV 2.0.0-beta-1](http://supercsv.sourceforge.net/release_notes.html)現在不在了。它包含許多錯誤修復和新功能(包括Maven支持和用於映射嵌套屬性和數組/集合的新Dozer擴展)。 – 2012-09-18 05:41:16

回答

1

只是要小心,如果你看過所有的地址和個人信息到內存中第一個(托馬斯曾建議) - 如果你只處理小CSV文件,那麼它的罰款,但如果你可能耗盡內存正在處理更大的文件。

作爲替代方案,我已經把在第一讀取地址的例子,然後把一個組合人/地址的詳細信息,同時它在人的詳細信息的讀取。

短短几件事情需要注意:

  • 我用CsvMapReader和CsvMapWriter因爲你 - 這意味着我不得不使用含有地圖存儲的地址的地圖。使用CsvBeanReader/CsvBeanWriter會讓這個更加優雅。

  • 您問題中的代碼實際上並未使用Super CSV讀取CSV(您正在使用ScannerString.split())。如果您的CSV在數據中包含逗號(這很可能與地址有關),那麼您會遇到問題,因此使用Super CSV可以更安全地使用Super 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行。 – 2012-08-21 12:01:14

+0

@jbel我猜你正在談論你的原始代碼。我的猜測是它發生在'cols1.get(0)[count] .equals(null)' - 這不是正確的方法來檢查是否爲null,因爲如果數組的元素爲null,那麼'.equals() '會拋出一個NullPointerException。它應該是'cols1.get(0)[count] == null'。說,我認爲你最好讓你的代碼更像我的例子 - 你有很多難以閱讀/冗餘的代碼! – 2012-08-22 07:41:03

+0

我使用你的代碼,我的appoligies我得到空指針異常錯誤,你有[代碼] combinedWriter.write(人,COMBINED_HEADER); [/ code] @獵狗狗。即時通訊假設這是用戶錯誤從我 – 2012-08-22 12:45:01

1

從您的評論,好像你有以下情況:

  • 文件1包含人
  • 文件2包含地址

然後你想通過某些關鍵字(一個或多個字段)匹配個人和地址,並將組合寫回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()