CSV 到 DataTable 将浮点值解析为日期

CSV to DataTable parsing float values as Date

我正在尝试将 CSV 解析为 VB.NET 项目中的数据表,问题是当我导入 CSV 文件时,值浮动的列如 ;2,08;2;0,82导入为 30/12/1899 02:08:0030/12/1899 02:00:00

如何防止 oledb 格式化数据?

这是我将 csv 加载到数据表的方式:

        Dim con As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & path & ";Extended Properties=""text;HDR=YES;FMT=Delimited(;)""")

        con.Open()
        Dim da As New OleDbDataAdapter(sqlquery, con)
        da.Fill(dt)

在 CSV 所在的同一文件夹中,我有 schema.ini,内容如下:

[anar_adm.csv]
Format=Delimited(;)

Schema.ini 文件有不同的选项,您可以在这里阅读。
Schema.ini File (Text File Driver)

您可以指定列数据类型以及小数点分隔符等。例如,定义 4 列的架构,其中:

  • ColNameHeader=True:数据文件包含列定义
  • Format=Delimited(;): 列之间用分号分隔
  • DecimalSymbol=,:小数点分隔符为逗号
  • Col(N)=ColumnName TYPE [WIDTH] [#]:列的名称和类型以及列的宽度(可选)。宽度值 ([#]) 是必需的。

如果列可能包含不是系统默认值的货币符号,请指定货币格式。例如,使用欧元 符号:

  • CurrencySymbol=[Symbol]:数据文件中使用的货币符号。

  • CurrencyPosFormat=[N]:正值的符号位置。这可以是以下 4 个值之一:
    0 = €1,1 1 = 1,1€ 2 = € 1,1 3 = 1,1 €

  • CurrencyNegFormat=[N]:同上,但可以指定更多的位置。有关可能值的列表,请参阅先前链接的文档

  • CurrencyDigits=[N]:货币的小数位数

  • CurrencyThousandSymbol=[Symbol]: 千位分隔符号

  • CurrencyDecimalSymbol=[Symbol]:小数点分隔符号

CharacterSet 指定 CSV 文件使用的编码方式。标准值为:

  • ANSI(本地代码页),OEMUnicode。必须使用其代码页指定其他编码。例如UTF-8需要指定为CodePage65001.
    系统中所有可用的代码页都列在此注册表项中:
    HKEY_CLASSES_ROOT\MIME\Database\Charset

使用此 CSV 内容:

ID;Description;Quantity;FloatValue;Price
1;String 1;100;10,56;€10,79
2;String 2;101;12,72;€200,34
3;String 3;33;100657,72;€0,98

一个Schema.ini文件可以如下:

[filename.csv]
ColNameHeader=True                First row is the Columns Header
MaxScanRows=0                     No auto-detect Column Type
CharacterSet=65001                UTF-8 file Format
Format=Delimited(;)               Columns delimiter
DecimalSymbol=,                   Decimals separator
NumberLeadingZeros=1              Below 1 values leading zeros (0,12)
CurrencySymbol=€                  Currency symbol (if present)
CurrencyPosFormat=0               Currency positive format: €1,1
CurrencyNegFormat=1               Currency negative format: -€1,1
CurrencyDigits=2                  Number of Decimal digits
CurrencyThousandSymbol=.          Thousands separator
CurrencyDecimalSymbol=,           Decimal separator
Col1=ID Long                      |-- Columns definition
Col2=Description Text WIDTH 50    |
Col3=Quantity Integer             |
Col4=FloatValue Double            |
Col5=Price Currency               |

[otherFilename.csv]
ColNameHeader=True
MaxScanRows=25                   | Auto-detect the data type, using 25 rows as sample
CharacterSet=ANSI
Format=Delimited()               | Standard delimiter: (,)

无论如何,我建议得到一个图书馆 CsvHelper

我维护了一个可以处理这种情况的库:Sylvan.Data.Csv

这是我编写的代码,用于验证它是否按预期工作。抱歉,这是在 C# 中,因为我不太了解 VB,应该很容易翻译。

using var reader = new StringReader("Name;Value1;Value2\nTest;2,08;0,82\n");

var schema = Schema.Parse("Name,Value1:float,Value2:float");

var options = new CsvDataReaderOptions {
    Schema = new CsvSchema(schema),
    // you would likely replace this with CurrentCulture
    // the default is InvariantCulture
    Culture = CultureInfo.GetCultureInfoByIetfLanguageTag("it-IT")
};
var csv = CsvDataReader.Create(reader, options);
var dt = new DataTable();
dt.Load(csv);

CsvDataReader 来自 Sylvan.Data.CsvSchema.Parse 行来自 Sylvan.Data,这是预发布的。您不必使用 Schema.Parse,而是可以提供您自己的 ICsvSchemaProviderAnswer.

中有一个简单模式提供程序的示例

与 OleDB 相比,它的优势在于它是完全托管的,不需要外部驱动程序,也不需要 schema.ini。它也是 much, much faster,如果性能是一个问题(事实上,它是 .NET 最快的)。缺点是您需要自己提供架构,而 OleDB 会尝试自动从数据中检测它(有时会出错)。