2016-08-12 1 views
2

Ich benutze StreamReader, um auf CSV-Textdatei zuzugreifen und alle Zeilen zu einem DataTable zu lesen.IndexOutOfRange Ausnahme beim Arbeiten mit DataTable

public static DataTable ConvertToDataTable(string filePath, int numberOfColumns) 
    { 
     DataTable tbl = new DataTable(); 

     for (int col = 0; col < numberOfColumns; col++) 
      tbl.Columns.Add(new DataColumn("Column" + (col + 1).ToString())); 

     string line; 
     System.IO.StreamReader file = new StreamReader("C:/ProgramData/3CX/Instance1/Data/Logs/CDRLogs/cdr.log"); 

     while ((line = file.ReadLine()) != null) 
     { 
      var cols = line.Split(','); 
      DataRow dr = tbl.NewRow(); 
      for (int cIndex = 0; cIndex < cols.Length + 1; cIndex++) 
      { 
       dr[cIndex] = cols[cIndex]; 
      } 
      tbl.Rows.Add(dr); 
     } 

Sobald ich habe alle CSV-Zeilen der Datatable hinzugefügt ich durch die Reihen zu durchlaufen wollen und remomve unerwünschte Zeilen auf Bedingungen.

DataTable dt = ConvertToDataTable("C:/ProgramData/3CX/Instance1/Data/Logs/CDRLogs", 4); 

     for (int i = 0; i < dt.Rows.Count; i++) 
     { 
      string duration = dt.Rows[i][1].ToString(); 
      if (duration == "") 
      { 
       dt.Rows[i].Delete(); 
      } 
      Console.WriteLine(i.ToString() + dt.Rows[i][1].ToString()); 
     } 

Das läuft ganz gut, bis ich die letzte Zeile zu erreichen, wo es scheint, durch eine Reihe zu Looping, der nicht existiert.

Jeder hat eine Idee, warum? Jede und jede Hilfe würde sehr geschätzt werden!

+2

Wo genau haben Sie Ausnahme? Vielleicht enthält die letzte Zeile keine zweite Spalte? '' 'dt.Rows [i] [1]' '' – tym32167

+0

Als Faustregel gilt: Löschen Sie nie ein Element einer Sammlung, die Sie iterieren. Auch bei einem Zyklus müssen Sie einige Aufmerksamkeiten (z. wie @Adimeus vorschlägt). Wenn Sie in Ihrem Code die letzte Zeile löschen, versuchen Sie in der nächsten Zeile auf Zeilen [i] zuzugreifen, die nicht mehr existieren. Auch wenn es sich nicht um die letzte Zeile handelt, bezieht sich Zeilen [i] auf die Zeile, die auf die Zeile folgt, die Sie gelöscht haben. Nicht was du auf Konsole schreiben willst, nehme ich an. –

Antwort

2

Wenn Sie die Zeile zu löschen, sollten Sie i nicht gesetzt = i + 1, weil Menge oder Zeilen wurde

 int i = 0; 
     while(i < dt.Rows.Count) 
     { 
      string duration = dt.Rows[i][1].ToString(); 
      if (duration == "") 
      { 
       dt.Rows[i].Delete(); 
      } 
      else 
      {i++;} 
      Console.WriteLine(i.ToString() + dt.Rows[i][1].ToString()); 
     } 
4

verringert Sie durchlaufen können die Zeilen Trog rückwärts die Indizes zu halten, wie sie sind.

for(int i = dt.Rows.Count - 1; i >= 0; i--) 
{ 
    dt.Rows[i].Delete(); 
} 
3

Beim Löschen Schleife rückwärts statt:

for (int i = 0; i < dt.Rows.Count; i++) 
{ 
    ...  
    dt.Rows[i].Delete(); 
    ... 
} 

Put
for (int i = dt.Rows.Count - 1; i >= 0 ; --i) 
{ 
    string duration = dt.Rows[i][1].ToString(); 

    if (duration == "") 
    { 
     dt.Rows[i].Delete(); 
    } 
    Console.WriteLine(i.ToString() + dt.Rows[i][1].ToString()); 
} 

Bei Sie Schleife haben vorwärts aus irgendeinem Grund ändern die Schleife in

for (int i = 0; i < dt.Rows.Count;) // do not increment here 
{ 
    string duration = dt.Rows[i][1].ToString(); 

    if (duration == "") 
    { 
     dt.Rows[i].Delete(); 
    } 
    else 
     i += 1; // ... but increment here 

    Console.WriteLine(i.ToString() + dt.Rows[i][1].ToString()); 
} 
1

Erhöhungsschritte i am Ende der Schleife

for (int i = 0; i < dt.Rows.Count;) 
{ 
    string duration = dt.Rows[i][1].ToString(); 
    if (duration == "") 
    { 
     dt.Rows[i].Delete(); 
    } 
    else 
    { 
     i++; 
    } 
    Console.WriteLine(i.ToString() + dt.Rows[i][1].ToString()); 
} 
1

Was ich in der Regel tun, wenn ich Elemente aus der Sammlung löschen muß ich Iterieren ist die Zeilen in einer anderen Sammlung löschen zu speichern. Etwas Ähnliches, für Ihren Fall:

int i = 0; // if you need to dump also the number of the row 
List<DataRow> toDelete = new List<DataRow>(); 
foreach (var row in dt.Rows) 
{ 
    string duration = row[1].ToString(); 
    if (duration == "") 
    { 
     toDelete.Add(row); 
    } 
    Console.WriteLine(i.ToString() + row[1].ToString()); 
    i++; 
} 
foreach (var rowToDelete in toDelete) 
    row.Delete(); 
0

Datatable dt = ConvertToDataTable ("C:/Programdata/3CX/Instance1/Data/Logs/CDRLogs", 4);

for (int i = 0; i < dt.Rows.Count; i++) 
    { 
     string duration = dt.Rows[i][1].ToString(); 
     if (duration == "") 
     { 
      dt.Rows[i].Delete(); 
      continue;    //Not printing deleted objects. So line after IF block won'nt exist. 
     } 
     Console.WriteLine(i.ToString() + dt.Rows[i][1].ToString()); 
    } 
Verwandte Themen