如何在C#中通过OLEDB导入CSV文件时指定分隔符

6
我需要在Microsoft SQL Server 2000中进行复杂的导入操作。由于使用DTS太复杂,我正试图用一小段C#程序来完成,但当我需要导入CSV文件时出现问题:该文件使用分号作为字段分隔符,而不是逗号,我无法让.NET的OLE DB提供者识别它。
我已经在网上找到了各种“解决方案”,例如在连接字符串中使用Extended Properties="Text; Format=Delimited" 或者``Extended Properties="Text; Format=Delimited(;)"以及使用schema.ini文件,但都没有成功。
这是我正在使用的实际代码:
DataTable Table = new DataTable();

using (OleDbConnection Connection = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0; Data Source={0}; Extended Properties=\"Text;HDR=Yes;Format=Delimited\""))
{
    Connection.Open();

    using (OleDbCommand Command = Connection.CreateCommand())
    {
        Command.CommandText = "select [Field 1], [Field 2] from [file.csv]";

        using (OleDbDataAdapter Adapter = new OleDbDataAdapter(Command))
        {
            Adapter.Fill(Table);
        }
    }
}

using (SqlConnection Connection = new SqlConnection("Data Source=server; Initial Catalog=database; User Id=user; Password=password;"))
{
    Connection.Open();

    using (SqlCommand Command = Connection.CreateCommand())
    {
        Command.CommandText = "insert into [table] ([field_1], [field_2], ...) values (@field_1, @field_2, ...)";

        Command.Parameters.Add("field_1", SqlDbType.Date, 0, "Field 1");
        Command.Parameters.Add("field_2", SqlDbType.VarChar, 100, "Field 2");
        ...

        using (SqlDataAdapter Adapter = new SqlDataAdapter())
        {
            Adapter.InsertCommand = Command;

            Adapter.Update(Table);
        }
    }
}

有没有关于如何使用分号作为字段分隔符而不依赖外部库的想法?
注: 1. “不依赖外部库”是因为我需要直接将文件导入数据库,而我找到的任何库都不能做到这一点(它们返回字符串),而我们的PHB(公司老板)不会为商业解决方案花一分钱。 2. 我知道可以通过DTS导入文件,但我需要在导入之前和之后执行复杂的工作流程和文件修改,并且那样会导致跳进和跳出DTS。 3. 对我来说,在DTS内部完成所有操作并不实际,因为我在ActiveX和VBScript编码方面不太熟练。
感谢您的帮助,Andrea。
编辑1-@andyb: schema.ini方法的测试程序代码:
String ConnectionString = String.Format("Provider=Microsoft.Jet.OLEDB.4.0; Data Source={0}; Extended Properties=\"Text\"", Environment.CurrentDirectory);

DataTable Table = new DataTable();

using (OleDbConnection Connection = new OleDbConnection(ConnectionString))
{
    Connection.Open();

    using (OleDbCommand Command = Connection.CreateCommand())
    {
        Command.CommandText = "select * from [file.csv]";

        using (OleDbDataAdapter Adapter = new OleDbDataAdapter(Command))
        {
            Adapter.Fill(Table);
        }
    }
}

你的代码在 OleDbConnection 字符串中使用了 SQL 提供程序语法,在 SqlConnection 字符串内部使用了 OLE DB 提供程序语法。这可能是问题所在吗? - Panagiotis Kanavos
@Panagiotis Kanavos:剪切和粘贴错误已经纠正。 - Albireo
3个回答

14

评论者是正确的,你的提供程序语法顺序是错误的。

然而,这不是问题所在。不幸的是,你无法在oledb连接字符串中指定自定义分隔符。相反,在与源文件相同的目录中创建一个名为schema.ini的文件,并包含以下内容:

[file.csv]
Format=Delimited(;)

有些笨拙,但它确实有效。


嗨,我已经尝试了schema.ini方法,但它没有起作用,我仍然只能导入一列。您可以在编辑后的问题正文中找到我在新测试程序中使用的代码。 - Albireo
我刚刚复制粘贴了你的代码并查询了 DataTable,它仍然可以正常工作。很抱歉要问这个问题,但是你在 schema.ini 中有正确的文件名吗? - andyb
谢谢你的回复,但这一定很让人沮丧。 你是否尝试过Microsoft Text Driver(也使用schema.ini)和System.Data.Odbc.OdbcConnection?例如: using (OdbcConnection cn = new OdbcConnection("Driver={Microsoft Text Driver (*.txt; *.csv)};DefaultDir=C:\MyDir;")) { ... } 你永远不知道... - andyb
schema.ini必须放在\bin文件夹中吗(而不是源代码文件夹中)? - tbone
1
它需要放在与您的数据相同的文件夹中。 - andyb
显示剩余3条评论

5

schema.ini文件必须保存为Unicode或ANSI格式,而非UTF-8格式。

您的数据文件也必须保存为Unicode格式,而非UTF-8格式。


1

您需要在schema.ini文件中写入您的csv文件名(不是[file.csv],例如:test.csv将在第0行具有带有[test.csv]文本的schema.ini:

[test.csv]
Format=Delimited(;)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接