代码之家  ›  专栏  ›  技术社区  ›  Rory MacLeod

使用DataReader和OLEDB Jet数据提供程序读取CSV文件时,如何控制列数据类型?

  •  14
  • Rory MacLeod  · 技术社区  · 16 年前

    Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\Data;Extended Properties="text;HDR=Yes;FMT=Delimited
    

    我使用该连接字符串打开ADO.NET OleDbConnection,并使用以下命令从CSV文件中选择所有行:

    select * from Data.csv
    

    House,Street,Town
    123,Fake Street,Springfield
    12a,Evergreen Terrace,Springfield
    

    调用House列的OleDbDataReader.GetDataTypeName方法将显示该列已被赋予数据类型“DBTYPE_I4”,因此从中读取的所有值都被解释为整数。我的问题是House应该是一个字符串——当我尝试从第二行读取House值时,OleDbDataReader返回null。

    4 回复  |  直到 16 年前
        1
  •  13
  •   Rory MacLeod    16 年前

    为了扩展Marc的答案,我需要创建一个名为Schema.ini的文本文件,并将其放在与CSV文件相同的目录中。除了列类型之外,此文件还可以指定文件格式、日期时间格式、区域设置以及列名(如果文件中未包含列名)。

    为了使我在问题中给出的示例起作用,模式文件应该如下所示:

    [Data.csv]
    ColNameHeader=True
    Col1=House Text
    Col2=Street Text
    Col3=Town Text
    

    [Data.csv]
    ColNameHeader=true
    MaxScanRows=0
    

    在现实生活中,我的应用程序从具有动态名称的文件导入数据,因此我必须动态创建Schema.ini文件,并在打开连接之前将其写入CSV文件所在的目录。

    更多详情可在此处找到- http://msdn.microsoft.com/en-us/library/ms709353(VS.85).aspx

        2
  •  10
  •   MarcE    5 年前

    您可以创建一个模式文件,告诉ADO.NET如何解释CSV,实际上是给它一个结构。

    试试这个: http://www.aspdotnetcodes.com/Importing_CSV_Database_Schema.ini.aspx

    MS Documentation

        3
  •  6
  •   Stuart Blackler    13 年前

    请查收

    http://kbcsv.codeplex.com/

    using (var reader = new CsvReader("data.csv"))
    {
        reader.ReadHeaderRecord();
        foreach (var record in reader.DataRecords)
        {
            var name = record["Name"];
            var age = record["Age"];
        }
    }
    
        4
  •  0
  •   Jon Breytman    7 年前

    您需要告诉驱动程序扫描所有行以确定模式。否则,如果前几行为数字,其余为字母数字,则字母数字单元格将为空。

    喜欢 Rory

    你一定有 MaxScanRows=0 在schema.ini中

    下面是一个代码示例:

        public static DataTable GetDataFromCsvFile(string filePath, bool isFirstRowHeader = true)
        {
            if (!File.Exists(filePath))
            {
                throw new FileNotFoundException("The path: " + filePath + " doesn't exist!");
            }
    
            if (!(Path.GetExtension(filePath) ?? string.Empty).ToUpper().Equals(".CSV"))
            {
                throw new ArgumentException("Only CSV files are supported");
            }
            var pathOnly = Path.GetDirectoryName(filePath);
            var filename = Path.GetFileName(filePath);
            var schemaIni =
                $"[{filename}]{Environment.NewLine}" +
                $"Format=CSVDelimited{Environment.NewLine}" +
                $"ColNameHeader={(isFirstRowHeader ? "True" : "False")}{Environment.NewLine}" +
                $"MaxScanRows=0{Environment.NewLine}" +
                $" ; scan all rows for data type{Environment.NewLine}" +
                $" ; This file was automatically generated";
            var schemaFile = pathOnly != null ? Path.Combine(pathOnly, "schema.ini") : "schema.ini";
            File.WriteAllText(schemaFile, schemaIni);
    
            try
            {
                var sqlCommand = $@"SELECT * FROM [{filename}]";
    
                var oleDbConnString =
                    $"Provider=Microsoft.Jet.OLEDB.4.0;Data Source={pathOnly};Extended Properties=\"Text;HDR={(isFirstRowHeader ? "Yes" : "No")}\"";
    
                using (var oleDbConnection = new OleDbConnection(oleDbConnString))
                using (var adapter = new OleDbDataAdapter(sqlCommand, oleDbConnection))
                using (var dataTable = new DataTable())
                {
                    adapter.FillSchema(dataTable, SchemaType.Source);
                    adapter.Fill(dataTable);
                    return dataTable;
                }
            }
            finally
            {
                if (File.Exists(schemaFile))
                {
                    File.Delete(schemaFile);
                }
            }
        }
    

    如果同时在多个线程中的同一目录上运行,则需要进行一些修改。