将CSV文件加载到DataTable - 使用JET.OLEDB读取CSV文件时出错

时间:2017-05-19 20:30:00

标签: c# asp.net-mvc csv asp.net-mvc-4

我使用使用C#和ASP.NET MVC4开发的应用程序从CSV文件填充MySQL中的表。我在加载CSV文件时遇到问题。

我正在阅读CSV文件,填写DataTable,对正则表达式进行验证并最终插入MySql数据库。大。

问题在于CSV文件中的数据格式。看起来当我读取Csv文件时,c#不区分字符串和双重。

当我用分隔符加载数字(双打)时,"。"或","该方法无法识别cvs文件的内容。

我已经审核了区域设置和语言中的格式,但没有得到解决方案。

请允许我解释一下,

VIEW

从视图中加载,我有点喜欢。

 //Here I can choose a Csv File and print the content
 @model Pharmtech.Models.myModule.FilesModel
 <div>
 @using (Html.BeginForm("UploadFile", "myModule", FormMethod.Post,
 new { enctype = "multipart/form-data" }))
 {
  <h3>Choose a Csv File</h3>
  <input type="file" name="file" />
  <input type="submit" value="Cargar">
 }
 <p>@TempData["Messages"]</p>

CONTROLLER

当提交激活 ActionResult UploadFile

    [HttpPost]
    public ActionResult UploadFile(HttpPostedFileBase file)
    {
        FilesModel model = new FilesModel();
        DataTable dt;

       //Check if file is not null
        if (file != null)
        {
            //Built the path
            string path = DateTime.Now.ToShortDateString().Replace("/", "-") 
                          + (file.FileName).ToLower();

            //Check File Extension
            if (model.FileCsv(path))
            {                    
                file.SaveAs(Server.MapPath("~/App_Data/" + path));
                dt = model.getDataTableFromCsvFile(Server.MapPath("~/App_Data/"), path);

                //Check if dt it's not empty
                if (dt.Rows.Count > 0)
                {
                    //Save in TempData["Messages"] the dt content
                    if (model.printDataTableFromCsv(dt))
                    {
                        TempData["Messages"] = model.AllData;
                    }
                }
                else TempData["Messages"] = "Csv File is Empty";
            }else TempData["Messages"] = "File it's not Csv File";
        }else TempData["Messages"] = "Please upload a Csv File";

       return RedirectToAction("Load");
    }    

MODEL

我在 FilesModel 模型

中编写了一些方法

验证Csv文件扩展名

    public bool FileCsv(string fileName)
    {
        string ext = Path.GetExtension(fileName);
        switch (ext.ToLower())
        {
            case ".csv": return true;
            default: return false;
        }
    }

从CSV文件中获取DataTable

//Get DataTable from Csv File    
    public  DataTable getDataTableFromCsvFile(String path, String file)
    {
        //Quit double spaces
        System.IO.File.WriteAllText(path + file, Regex.Replace
               (System.IO.File.ReadAllText(path + file), "  ", " "));

        //Defining connection
        string connectionStringCsv = @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" +
                path + ";Extended Properties='text;HDR=Yes;FMT=Delimited'";
        DataTable dt = new DataTable();

        try
        {
            OleDbConnection objConn = new OleDbConnection(connectionStringCsv);
            objConn.Open();

            OleDbCommand objCmdSelect 
              = new OleDbCommand("select * from [" + file + "]", objConn);
             OleDbDataAdapter objAdapter = new OleDbDataAdapter();

            objAdapter.SelectCommand = objCmdSelect;
            objAdapter.Fill(dt);
            objConn.Close();
        }
        catch (Exception ex)
        {
            //Do something
        }

        return dt;
    }

最后打印DataTable内容

 public string AllData;
 public bool printDataTableFromCsv(DataTable masterCsv)
 {
     AllData = "";
     int row = 0;
     //Check if DataTable it's not emtpy
     if (masterCsv.Rows.Count > 0)
     {
         //Going through DataTable and print rows
         foreach (DataRow rows in masterCsv.Rows)
         {
           AllData += "Row: " + row 
             + "=" + rows["DATA"].ToString() + ". ";
           row++;
                }
         }            
          if (row != 0) { return true; }
          else { return false; }
}

INPUT和OUTPUTS

一些例子:

输出1

输入1,文件内容

 //DATA
 //30.33
 //20.45

 //Output is 1         
 //I get: "Row: 0=3033. Row: 1=2045" 
  //**Is to say, remove the "." 

输出2

输入2,文件内容

 //DATA
 //20.33
 //Hello World

 //Output is
 //Row: 0=2033.Row: 1=.
 //**Is to say, remove the letters

输出3

输入3,当文件内容

 //DATA
 //20.33
 //Hello World
 //This is, a problem

 //Output is        
 //Row: 0=20.33.Row: 1=Hello World.Row: 2=This is, a problem.

假设

我猜错误在于读取csv,C#尝试为DataTable的列分配一种数据

有时,我选择一个只有两倍打印的csv文件&#34; File Empty&#34; 我试过.csv和.csv MS-DOS

有人知道我做错了什么吗? 谢谢你的帮助

2 个答案:

答案 0 :(得分:1)

  

我猜错误在于读取csv,C#尝试为DataTable的列分配一种数据

如果您的列具有混合数据类型,或者包含可以作为不同数据类型读取的数据(即“4-4-97”,可以是日期或字符串),则应使用imex切换你的连接字符串。

"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + someVariablePath + ";Extended Properties=\"text;HDR=Yes;FMT=Delimited;IMEX=1;\"";

或者使用模式文件并获得对数据读取方式的更多控制。请注意,如果切换到较新的数据访问组件(Provider=Microsoft.ACE.OLEDB.12.0),则IMEX开关无效,如果您希望控制数据类型,则必须使用模式文件。

Schema file Documentation

[myfile.txt]
Format=CSVDelimited
ColNameHeader=True
MaxScanRows=5

并不是C#尝试定义类型,它是做出该决定的数据驱动程序,并告诉您的代码将要发生什么。驱动程序读取第一行n并定义类型。然后通过n行传递一个不再与该类型相匹配的值。

col1
1
2
3
4
5
a
7
true
9

上面的列可能会产生问题。根据前5条记录,我们正在处理int。因此,在进行列定义时,该列被视为int。从那时起,您的代码期望看到该列中的数字。但是在记录6中,有一个字符串。记录8可以是stringbool。数据驱动程序并不在意,但是当您在需要数字时为"a"提供类似的代码时,代码会执行此操作。

答案 1 :(得分:0)

部分解决方案引用双引号内的CSV值(这样,JET会将所有读取值视为字符串),然后从C#中解析它们。

经过多次尝试解决并评估负载消耗时间后,我决定不使用Jet.OLEDB

我认为有更合适的方法,例如使用LINQ。

我还发现了这两个项目:

Sebastian Lorien

A fast CSV Reader

A portable and Efficient parse for float files

Delimited Text Extension File

让我分享这个答案,帮助我找到解决方案:

How to read a CSV file into a .NET Datatable

非常感谢