【问题标题】:Loading a CSV File to DataTable - Error reading CSV File With JET.OLEDB将 CSV 文件加载到 DataTable - 使用 JET.OLEDB 读取 CSV 文件时出错
【发布时间】:2017-05-19 20:29:59
【问题描述】:

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

我正在读取 CSV 文件,填充 DataTable,对正则表达式进行验证,最后插入 MySql 数据库。太好了。

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

当我只加载带分隔符的数字(双精度)时,“。”或 "," 该方法无法识别 cvs 文件的内容。

我查看了区域设置和语言的格式设置,但没有找到解决方案。

请解释一下,

查看

从视图加载我有点喜欢。

 //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>

控制器

当提交活动时 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");
    }    

型号

我在FilesModelModel

中写了一些方法

验证 Csv 文件扩展名

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

从 CSV 文件中获取数据表

//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; }
}

输入和输出

一些例子:

输出 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 文件,其中只有两倍的打印是“文件空” 我尝试使用 .csv 和 .csv MS-DOS

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

【问题讨论】:

  • 你能告诉我们哪一行是异常的地方吗?
  • 这个问题讲的太多了。您能否隔离导致问题的单行,如果该问题是在读取 csv、将其处理为数据表或将其保存到 MySql 中?
  • 我在打印 DataTable 时遇到错误。我退出了所有关于数据库的验证和操作。
  • 所以你在 AllData[row] = "Row: " + row + " -> Field DATA " + "= " + rows["DATA"].ToString(); ?错误信息是什么?
  • {System.InvalidCastException:无法将“System.String”类型的对象转换为“System.String []”类型。程序在显示 TempData["Messages"] 的内容时中断

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


【解决方案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" 之类的内容时,您的代码需要一个数字。

【讨论】:

  • 感谢朋友,这是对正在发生的事情的清晰解释。我在连接字符串中测试了 IMEX=1 并且不起作用。我不确定是否创建模式,因为此方法必须适用于二十七 (27) 个不同的 Csv 文件(不同的名称文件、不同的标题,我需要在今天之前构建文件名),但我会尝试的。非常感谢。
【解决方案2】:

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

经过多次尝试解决方案和负载中消耗时间的评估,我决定不使用Jet.OLEDB

我认为有更合适的方法可以做到这一点,例如使用 LINQ。

我还发现了这两个项目:

A fast CSV Reader by 塞巴斯蒂安·洛里恩

A portable and Efficient parse for float files

Delimited Text Extension File

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

How to read a CSV file into a .NET Datatable

非常感谢

【讨论】:

    猜你喜欢
    • 2015-06-24
    • 2020-10-30
    • 2018-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多