2014-01-22 3 views
0

Я пытаюсь прочитать файл csv с помощью команды oledb. После этого я использую. Этот код выполняется плавно. Но мне нужно удалить первую строку из файла csv и установить вторую строку в качестве заголовка столбца для datatable. Является ли это возможным?Чтение csv с использованием команды OLEDB

static DataTable ImportCsvFileToDataTable(string filename, string fullPath) 
{ 
    FileInfo file = new FileInfo(fullPath); 

    using (OleDbConnection con = 
       new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=\"" + 
       file.DirectoryName + "\";Extended Properties='text;HDR=Yes;FMT=Delimited(,)';")) 
    { 
     using (OleDbCommand cmd = new OleDbCommand(string.Format 
            ("SELECT * FROM [{0}]", file.Name), con)) 
     { 
      con.Open(); 

      // Using a DataTable to process the data 
      using (OleDbDataAdapter adp = new OleDbDataAdapter(cmd)) 
      { 
       DataTable tbl = new DataTable(filename); 
       adp.Fill(tbl); 
       return tbl; 
      } 
     } 
    } 
} 

ответ

1

Я пролил много крови, пытаясь разработать идеальный метод для импорта CSV в DataTable. Вот результат. Он анализирует первую строку как заголовки столбцов. Этот метод работает с Ace OleDB 12, но он также не должен работать с Jet OleDB 4.

public static DataTable FromCSV(string FilePath, char Delimiter = ',') 
{ 
    DataTable dt = new DataTable(); 
    Dictionary<string, string> props = new Dictionary<string, string>(); 

    if (!File.Exists(FilePath)) 
     return null; 

    if (FilePath.EndsWith(".csv", StringComparison.OrdinalIgnoreCase)) 
    { 
     props["Provider"] = "Microsoft.Ace.OLEDB.12.0"; 
     props["Extended Properties"] = "\"Text;FMT=Delimited\""; 
     props["Data Source"] = Path.GetDirectoryName(FilePath); 
    } 
    else 
     return null; 

    StringBuilder sb = new StringBuilder(); 

    foreach (KeyValuePair<string, string> prop in props) 
    { 
     sb.Append(prop.Key); 
     sb.Append('='); 
     sb.Append(prop.Value); 
     sb.Append(';'); 
    } 

    string connectionString = sb.ToString(); 

    File.Delete(Path.GetDirectoryName(FilePath) + "/schema.ini"); 
    using (StreamWriter sw = new StreamWriter(Path.GetDirectoryName(FilePath) + "/schema.ini", false)) 
    { 
     sw.WriteLine("[" + Path.GetFileName(FilePath) + "]"); 
     sw.WriteLine("Format=Delimited(" + Delimiter + ")"); 
     sw.WriteLine("DecimalSymbol=."); 
     sw.WriteLine("ColNameHeader=True"); 
     sw.WriteLine("MaxScanRows=1"); 
     sw.Close(); 
     sw.Dispose(); 
    } 

    using (OleDbConnection conn = new OleDbConnection(connectionString)) 
    { 
     conn.Open(); 
     OleDbCommand cmd = new OleDbCommand(); 
     cmd.Connection = conn; 
     cmd.CommandText = "SELECT * FROM [" + Path.GetFileName(FilePath) + "] WHERE 1=0"; 
     OleDbDataAdapter da = new OleDbDataAdapter(cmd); 
     da.Fill(dt); 

     using (StreamWriter sw = new StreamWriter(Path.GetDirectoryName(FilePath) + "/schema.ini", true)) 
     { 
      for (int i = 0; i < dt.Columns.Count; i++) 
      { 
       string NewColumnName = dt.Columns[i].ColumnName.Replace(@"""", @""""""); 
       int ColumnNamePosition = NewColumnName.LastIndexOf("#csv.", StringComparison.OrdinalIgnoreCase); 
       if (ColumnNamePosition != -1) 
        NewColumnName = NewColumnName.Substring(ColumnNamePosition + "#csv.".Length); 
       if (NewColumnName.StartsWith("NoName")) 
        NewColumnName = "F" + (i + 1).ToString(); 
       sw.WriteLine("col" + (i + 1).ToString() + "=" + NewColumnName + " Text"); 
      } 
      sw.Close(); 
      sw.Dispose(); 
     } 

     dt.Columns.Clear(); 
     cmd.CommandText = "SELECT * FROM [" + Path.GetFileName(FilePath) + "]"; 
     da = new OleDbDataAdapter(cmd); 
     da.Fill(dt); 
     cmd = null; 
     conn.Close(); 
    } 

    File.Delete(Path.GetDirectoryName(FilePath) + "/schema.ini"); 
    return dt; 
} 
0

Возможно, что-то вроде этого:

tbl.Rows[0].Delete(); 
    DataRow r = tbl.Rows[0]; 
    foreach(DataColumn c in tbl.Columns) 
    { 
     tbl.Columns[c.ColumnName].ColumnName = r[c.ColumnName].ToString(); 

    } 
    tbl.Rows[0].Delete(); 
0

Там нет встроенного способа сказать OLEDB использовать вторую строку для заголовков вместо первой строки.

Вам нужно будет открыть файл CSV, удалив первую строку и снова сохранить его. К счастью, это довольно легко сделать:

var lines = File.ReadAllLines(oldFileName); 
File.WriteAllLines(newFileName, lines.Skip(1)); 

(Добавить .ToArray() после Skip(1), если вы используете версию .NET < 4.)

Смежные вопросы