问题描述
我试图在 VB.NET 项目中将 CSV 解析为 DataTable,问题是当我导入 CSV 文件时,值像 ;2,08;2;0,82
这样浮动的列被导入为 { {1}} 和 30/12/1899 02:08:00
如何防止 oledb 格式化数据?
这是我如何将 csv 加载到数据表:
30/12/1899 02:00:00
在 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)
包含以下内容:
schema.ini
解决方法
我维护一个可以处理这种情况的库: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.Csv
,Schema.Parse
行来自 Sylvan.Data
,这是预发布的。您不必使用 Schema.Parse
,而是可以提供自己的 ICsvSchemaProvider
。此 Answer 中有一个简单架构提供程序的示例。
与 OleDB 相比,它的优势在于它是完全托管的,不需要外部驱动程序,也不需要 schema.ini。它也是 much,much faster,如果性能是一个问题(实际上,它是 .NET 最快的)。缺点是您需要自己提供架构,而 OleDB 会尝试从数据中自动检测它(有时会出错)。
,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]
:十进制分隔符
字符集指定 CSV 文件使用的编码。标准值为:
-
ANSI
(本地代码页)、OEM
、Unicode
。其他编码必须使用它们的 CodePage 指定。例如,需要将 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