2011-08-17 88 views
0

我讀在格式CSV文件到列表:添加項目基礎上的selectedIndex

10009279,D002158 ,, 「摩羅賓遜存款」,38.1139,-105.34557,NA, 「美國」,科羅拉多州,卡斯特,B,「鋁,鉀」 ,,

我想寫出僅基於從最初的CSV文件中選擇列的新CSV文件,因此產生的結構將類似於:

- 105.34557,38.1139,「Mount Robinson礦牀」,「Custer」鋁,鉀「

我曾嘗試:

StreamWriter writer = new StreamWriter(@textBox2.Text); 
string[] lines = File.ReadAllLines(@textBox1.Text); 
foreach (string line in lines) 
{ 
    string[] fields = line.Split(','); 
    writer.WriteLine(string.Format("{0},{1},{2},{3}", fields[LONcomboBox.SelectedIndex], fields[LATcomboBox.SelectedIndex], fields[NAMEcomboBox.SelectedIndex], fields[10 + 13])); 
} 
writer.Close(); 

與下列問題的工作:嵌入雙引號

  1. 逗號似乎不正確處理
  2. concatonating多的Fileds似乎失敗(這是解決謝謝你的答案)

任何建議,將不勝感激!

我也試圖使用FileHelpers,但似乎無法讓它使用列的索引工作。

+0

你在A點是什麼意思? 再加上string.Format(...)行的輸出。調試並在觀察窗口中看到它。 – Zenwalker

+0

在A點中,當csv中的字段類似「field,two」時,我需要解析器忽略雙引號集之間的逗號,將嵌入逗號視爲字符串的一部分而不是字段分隔符。 – Fred

回答

0

根據Doug的建議,我回顧了一些csv解析器。我第一次嘗試FileHelpers,但我真的無法讓它在使用標題行時工作。對列的引用總是以列名爲結尾,而不是索引。我真的需要通過列的索引引用我的列,因爲它與我的選擇匹配一個列表框和checkedlistbox。我審查了A FAST CSV READER這實際上對我來說是訣竅。下面是我如何實現它:

private void button2_Click(object sender, EventArgs e) 
    { 

     using (CsvReader csv = new CsvReader(new StreamReader(@textBox1.Text), true)) 
     { 
      int fieldCount = csv.FieldCount; 
      string[] headers = csv.GetFieldHeaders(); 

      /// Evaluate the checkedlistbox 
      string comment = ""; 
      List<Int32> comment_indices = new List<Int32>(); 
      List<String> lines = new List<String>(); 
      for (int x = 0; x <= checkedListBox1.CheckedItems.Count - 1; x++) 
      { 
       // add selected item's index to list 
       comment_indices.Add(checkedListBox1.CheckedIndices[x]); 
      } 

      while (csv.ReadNextRecord()) 
      { 

       /// Use the SelectedIndex to match the header and column 
       string base_string = csv[LONcomboBox.SelectedIndex] + "," + csv[LATcomboBox.SelectedIndex] + "," + csv[NAMEcomboBox.SelectedIndex] + ","; 
       //MessageBox.Show(base_string); 

       /// Try to get the row value -- this is the row count - starting at 0 excluding headers I think 
       //MessageBox.Show("Is this the row count?" + csv.CurrentRecordIndex); 
       comment = ""; 
       /// Get the comment 
       foreach (Int32 indices in comment_indices) 
       { 
        comment = comment + csv[indices] + " "; 
       } 
       //MessageBox.Show(base_string + '"' + comment + '"'); 
       string completed_string = base_string + '"' + comment + '"'; 
       lines.Add(completed_string); 
      } 

      StreamWriter writer = new StreamWriter(@textBox2.Text); 
      foreach (string line in lines) 
      { 
       writer.WriteLine(line); 
      } 
      writer.Close(); 
     }   
     MessageBox.Show(" Finished Writing file " + "\n" + "\n" + " " + textBox2.Text); 
    } 

代碼項目網站上有很好的實例,它解決了我的問題。希望這可以幫助別人!

0

關於(a), 您是否有任何控制csv輸入文件的格式?如果是這樣,那麼一個簡單的選擇是使用逗號分隔符。也許|代替?

要回答(B),

而不是fields[10 + 13]

嘗試fields[10] + fields[13]

否則所有你正在做的是試圖發現場23,這可能不存在。

+0

按照他的說法,是嵌入黑/白「」「我不知道如何在CSV中發生這種情況,除非它本身的列值 – Zenwalker

+0

我沒有任何真正的控制CSV文件的結構,所以我必須解決奇怪的結構...感謝您如何concaconate這兩個領域。我會給它一個鏡頭。 – Fred

+0

祝你好運。如果答案有幫助,不要忘記加註他們。 :) –

0

你可能想尋找一個CSV解析器,有一些好的建議在這裏:High scoring answer on StackOverflow

你不得到與最後一個參數一個例外?

我想你想要更多的東西一樣:

writer.WriteLine(的String.Format( 「{0},{1},{2},{3}」, 領域[LONcomboBox.SelectedIndex]字段[LATcomboBox.SelectedIndex],字段[NAMEcomboBox.SelectedIndex],字段[10] +字段[13]));

但是我可能會對任何沒有檢查數組索引的人感到憤怒,因此請確保在引用字段之前驗證至少有14列[13]。

+0

謝謝大家迄今爲止的答案,我會嘗試一下,並回應一次我有機會嘗試一下。 – Fred

+0

我嘗試使用FileHelpers然後嘗試實現上面的Davendra的代碼後,最終使用代碼項目中的csv分析器。來自Code Project [快速CSV閱讀器](http://www.codeproject.com/KB/database/CsvReader.aspx)的CSV解析器效果很好,並且允許我選擇FileHelpers所沒有的字段索引(或者至少我能夠不知道如何去做)。 – Fred

0

下面的代碼實現解析器還有CSV作家,

private void ProcessCSV(string sourceCsvFilePath, string destCsvFilePath) 
{ 
    // Read contents of source file 
    var lines = File.ReadAllLines(sourceCsvFilePath, Encoding.Default); 

    // Process the old file contents 
    var table = new List<List<string>>(); 
    foreach (var line in lines) 
    { 
     var cells = new List<string>(); 
     if (line[0] == ',') 
     { 
      cells.Add(string.Empty); 
     } 

     for (int i = 0; i < line.Length; i++) 
     { 
      if (line[i] == '\"') 
      { 
       var cellBuilder = new StringBuilder(line[i].ToString()); 
       i++; 
       while (i < line.Length && line[i] != '\"') 
       { 
        cellBuilder.Append(line[i].ToString()); 
        i++; 
       } 
       cells.Add(cellBuilder.ToString().Trim('\"')); 
      } 
      else if (line[i] != ',') 
      { 
       var cellBuilder = new StringBuilder(line[i].ToString()); 
       i++; 
       while (i < line.Length && line[i] != ',') 
       { 
        cellBuilder.Append(line[i].ToString()); 
        i++; 
       } 

       cells.Add(cellBuilder.ToString().Trim('\"')); 
      } 
      else if (i > 0 && line[i - 1] == ',' && line[i] == ',') 
      { 
       cells.Add(string.Empty); 
      } 
     } 

     if(line[line.Length - 1] == ',') 
     { 
      cells.Add(string.Empty); 
     } 

     table.Add(cells); 
    } 

    // Create a new table in the order: OldTable.Col2, OldTable.Col4, OldTable.Col0, "OldTable.Col1 OldTable.Col5 OldTable.Col6" 
    var newTable = new List<List<string>>(); 

    foreach (var row in table) 
    { 
     var cells = new List<string>(); 
     cells.Add(row[2].Contains(',') ? string.Concat("\"", row[2], "\"") : row[2]); 
     cells.Add(row[4].Contains(',') ? string.Concat("\"", row[4], "\"") : row[2]); 
     cells.Add(row[0].Contains(',') ? string.Concat("\"", row[0], "\"") : row[2]); 

     string str = string.Format("{0} {1} {2}", row[1], row[5], row[6]); 
     cells.Add(str.Contains(',') ? string.Concat("\"", str, "\"") : str); 

     newTable.Add(cells); 
    } 

    // Prepare the file contents 
    var linesToWrite = new string[newTable.Count]; 
    int lineCounter = 0; 
    foreach (var row in newTable) 
    { 
     StringBuilder rowBuilder = new StringBuilder(); 
     foreach (var cell in row) 
     { 
      rowBuilder.AppendFormat("{0},", cell); 
     } 

     linesToWrite[lineCounter++] = rowBuilder.ToString().Trim(','); 
    } 

    // Write the contents to CSV 
    File.WriteAllLines(destCsvFilePath, linesToWrite, Encoding.Default); 
} 

您將需要添加檢查File.Exists和索引檢查(以確保列存在,你訪問它之前)。 如果您對更簡潔的方法感興趣,那麼您可以嘗試使用正則表達式與Regex class進行解析。

+0

到目前爲止,這似乎工作得很好 - 更改了cells.Add ---> row [2]);最後需要每行更改。我試過:cells.Add(row [LONcomboBox.SelectedIndex] .Contains(',')?string.Concat(「\」「,row [LONcomboBox.SelectedIndex],」\「」):row [LONcomboBox.SelectedIndex]) ;這樣我可以使用組合框中選定的值。從csv文件入站的真實數據是:10009279,D002158,「Mount Robinson deposit」,38.1139,-105.34557,NA,「美國」,科羅拉多州,卡斯特,B,「鋁,鉀」如果您注意到它有空的領域,我如何處理這些? – Fred

+0

對不起,這是相當混亂,我編輯原始問題,以顯示我解析一些真實的數據,包括空字段。 – Fred

+0

我已經更新了方法,它現在處理空單元格。您可能需要根據您希望在輸出中看到的值更新列索引。 –

1

好的。快速和骯髒的簡短的回答我只是使用Linq和正則表達式。

private void processCSV(string inputFileName) 
    { 
     Regex regexObj = new Regex(@"\s*(?:""(?<val>""[^""]*(""""[^""]*)*"")\s*|(?<val>[^,]*))(?:,|$)"); 
     List<List<Match>> elements = File.ReadAllLines(inputFileName) 
      .Select<string,List<Match>>(x=>regexObj.Matches(x).Cast<Match>().ToList()).ToList();    
     List<string> newLines = elements.Select(y=>y.Select(z=>z.Groups["val"].Value).ToList()) 
             .Select(z=>string.Format("{0},{1},{2},{3}",z[0],z[1],z[2],z[4]+z[5])) 
             .ToList(); 

     //Write newlines somewhere 
    } 

但是對於生產水平的代碼,你真的應該使用CSV解析庫像http://www.codeproject.com/KB/database/CsvReader.aspx

我敢肯定有更好的走出這僅僅是第一次見到。