【问题标题】:C# csv loaded into datatable missing columnsC# csv 加载到数据表缺失的列中
【发布时间】:2018-05-12 10:38:13
【问题描述】:

我已将 csv 加载到数据表中,但某些列在非空白时被读取为空白。我最初提出这个问题时只有标题有问题,但我现在在我的数据行中也看到了这个问题,所以我需要重新询问......我的数据集有什么问题以及为什么某些列被读取为空白?

目前,此设置将读取第 1-7 列的数据(我不需要 8-10)。为除第 4 列之外的所有列正确填充了数据。奇怪的是,我测试了两个文件,它们的结构都相似,但其中一个在第 4 列中有值,另一个没有。完整的代码被设置为循环遍历许多文件,检查数据的开始和结束,然后加载到 sql server。

CSV 示例:

By OrgID/Location

As of:   December 6, 2017 at 10:13 AM 

Date Range: summaryYM           2017M08 to 2017M08

"orgid=13778 medType=' '"
"col1","col2","col3","col4","col5","col6","col7","col8","col9","col10"
13778,140242,"2A","2017M08",0,0.058,78,".",".",
13778,140242,"2B","2017M08",0,0.014,19,".",".",
13778,140242,"2C","2017M08",0,0.083,133,".",".",
13778,140242,"2ICU","2017M08",0,0.099,114,".",".",
13778,140242,"3 ICU","2017M08",0,0.076,88,".",".",

代码

//open connection to csv
string connStrCsv = string.Format(@"Provider=Microsoft.Jet.OleDb.4.0; Data Source={0};Extended Properties=""Text;HDR=NO;FMT=Delimited"""
      , Path.GetDirectoryName(file));
OleDbConnection connCsv = new OleDbConnection(connStrCsv);
connCsv.Open();

//store csv data in datatable
string readCsv = "select * from [" + Path.GetFileName(file) + "]";
OleDbDataAdapter adapter = new OleDbDataAdapter(readCsv, connCsv);
DataSet ds = new DataSet();
adapter.Fill(ds, "sheet1");
DataTable table = ds.Tables["sheet1"];
connCsv.Close();

//find header to define start of data
int start = 0;
StreamReader headerSearch = null;
int incr = 0;
headerSearch = new StreamReader(file);
while (!headerSearch.EndOfStream)
{
  incr++;
  string line = headerSearch.ReadLine();
  if (line.Contains("\"col1\",\"col2\",\"col3\",\"col4\",\"col5\",\"col6\""))
  {
      start = incr;
  }
}
headerSearch.Close();

//load each row of excel into SQL server until first empty row
string sqlConnStr = "Data Source=mysource;Initial Catalog=mydatabase;Trusted_Connection=Yes;Integrated Security=SSPI;";
SqlConnection connSql = new SqlConnection(sqlConnStr);
connSql.Open();

int end = start;
while (table.Rows[end][0].ToString().Length != 0)
{
  string sql = string.Format
  (@"
  delete from schema.table
  where ss_col1      =  {0}    
      and ss_col2    = '{1}' 
      and ss_col3    = '{2}' 
      and ss_col4    = '{3}';

  insert into schema.table
  values ({4}        
      ,'{5}'         
      ,'{6}'         
      ,'{7}'         
      , {8}          
      ,'{9}'         
      ,'{10}'        
      ,getdate()
      ,user_name()
      ,getdate()
      ,user_name());"
      //delete statement variables
      , table.Rows[end][0].ToString()
      , table.Rows[end][2].ToString()
      , table.Rows[end][3].ToString()
      , infTypes[i]
      //insert statement variables
      , table.Rows[end][0].ToString()
      , table.Rows[end][2].ToString()
      , table.Rows[end][3].ToString()
      , infTypes[i]
      , table.Rows[end][4]
      , table.Rows[end][5].ToString()
      , table.Rows[end][6]
  );

  SqlCommand execSql = new SqlCommand(sql, connSql);
  execSql.ExecuteNonQuery();

  end++;
}
connSql.Close();

【问题讨论】:

  • 找出“垃圾”的来源并修复它。
  • 检查 4-7 中的空白列:if(row[4].ToString() == "" && row[5].ToString() == "" && row[6].ToString() == "" && row[7].ToString() == "") { // then cols 4-7 are blank },除非我在这里遗漏了一些东西。我不熟悉 OleDB,但在这个代码示例中,数据实际上来自那里,而不是来自 CSV 文件(即使它最初来自 CSV),所以我会编写一个查询来过滤你选择的内容根据您的需要,或使用数据库约束来防止垃圾数据首先出现在此处。
  • 感谢您到目前为止的回复,看来我没有清楚地解释自己。我不能只修复垃圾,因为文件来自我无法控制的外部源。 csv 中有大约 200 行,其中可能只有 30 行具有我需要的数据,但是由于垃圾数量的变化,每个文件的 30 行都会发生变化。我在第 4-7 列中得到的空白列应该有数据。我需要每列 1-7 来匹配一个字符串。

标签: c# csv datatable dataset


【解决方案1】:

您必须将其加载到数据表中吗? 如果 "header1","header2","header3","header4","header5","header6" 是唯一的,那么在找到之前读取 csv 文件会不会更容易?

例子……

StreamReader Reader = null;
string FilePath = "Your File Path";
try
{
  Reader = new StreamReader(FilePath);
  while(Reader.Peek() > 0)
  {
    string line = Reader.ReadLine();
    bool HeaderFound = false;
    if(line == "What ever your headers are")
    {
      HeaderFound = true;
    }
    if(HeaderFound)
    {
      //Here is all your data you were looking for.
     //Do whatever you need to do with it now.
    }
  }
} catch(exception e)
{/*Deal with the issues*/}
finally
{
  if(Reader != null)
  {
    Reader.Close();
    Reader.Dispose();
  }
}

【讨论】:

  • 感谢您的建议。我最初使用流式阅读器解决了标头问题,但在对 csv 进行了一些更改后,我开始看到数据集存在相同的问题。我现在重新提出这个问题,并希望获得数据集适配器的解决方案。填充技术,而不是必须使用 streamreader 和拆分语句重新开发。
  • 原来微软构建的数据集适配器是一个谜,它究竟是如何工作的,这就是为什么我错过了一些列。因此,这个流式阅读器选项是我可以控制并确切知道我的 csv 发生了什么的唯一方法。我最终不得不使用这个流式阅读器和拆分选项 - 结果并没有更多的重新开发。
猜你喜欢
  • 2022-01-20
  • 2018-03-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-16
  • 2017-01-14
  • 1970-01-01
相关资源
最近更新 更多