CsvHelper.CsvReader 不会读取 CSV 文件

问题描述 投票:0回答:1

首先,我的程序应该将 CSV 文件的内容附加到 SQL Server 中的 SQL 表中,当您使用文本框“pathInputTextBox”中输入的路径和文本框“tableInputTextBox”中的表名称时按按钮“toSqlButton”。完成这部分后,我还将使用不同的按钮针对不同类型的数据库执行此操作,但目前读取 csv 文件已经失败。 (我什至不知道它之后是否可以正确附加数据,但我是一个愚蠢的小伙子,先编写所有代码,然后解决一个又一个问题,所以当我到达那里时我会跨过那座桥。 )
错误是:

CsvHelper.ReaderException: 'No header record was found.  
IReader state:  
   ColumnCount: 0  
   CurrentIndex: -1  
   HeaderRecord:  

从线上

csv.ReadHeader();  

在 toSQLButton_Click 事件中。通过调试,我发现这是由于 ReadCSV 方法返回 null 造成的,每当读取文件失败时都会返回 null。
我尝试解决此问题的一些方法包括编写不同的方法来读取文件(例如 TextReader),这些方法仍然可以使用类似的语法和编写

CsvReader csv = new CsvReader(reader, new CsvConfiguration(CultureInfo.InvariantCulture) {Delimiter = ";", HasHeaderRecord = true });  

而不是

CsvReader csv = new CsvReader(reader, CultureInfo.InvariantCulture);

但这些似乎都不起作用。我 100% 确信我写入文本框的文件路径应该有效(是的,我在将其复制到文件资源管理器中后删除了“s)。我已经在互联网上进行了筛选并向 ChatGPT 寻求帮助,但我在我的智慧结束了,感觉这一定是一些非常微小的、愚蠢的菜鸟错误,被植入到代码中的某个地方,应该是显而易见的。请帮助我,我期待您的回复。

代码:

/// <summary>
/// Reads the CSV file specified by the data path and returns CsvReader information.
/// </summary>
/// <param name="pathString"></param> Data path of the CSV file.
/// <returns> CsvReader information of the CSV file or null in case of failure. </returns>
private CsvReader ReadCSV(string pathString)
{
    try
    {
        var reader = new StreamReader(pathString);
        CsvReader csv = new CsvReader(reader, new CsvConfiguration(CultureInfo.InvariantCulture) { Delimiter = ";", HasHeaderRecord = true });
        reader.Close();
        return csv;
    }
    catch (FileNotFoundException)
    {
        MessageBox.Show("File not found. Please check the entered file path.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
    catch (Exception ex)
    {
        MessageBox.Show("An error occurred while reading the CSV file: " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
    return null; 
}

/// <summary>
/// Writes the content of the CSV file from the pathInputTextBox to the SQL Server on toSqlButton click.
/// </summary>
/// <param name="sender"></param> Sender information.
/// <param name="e"></param> Event stuff.
private void toSqlButton_Click(object sender, EventArgs e)
{
    string sqlConnection = "Data Source=VERYCOOLDATASOURCE\\SQLEXPRESS;Initial Catalog=VeryCoolDB;Integrated Security=True";
    CsvReader csv = ReadCSV(pathInputTextBox.Text);
    if (csv != null) 
    {
        using(SqlConnection sqlconn = new SqlConnection(sqlConnection))
        {
            // Get CSV column names for comparison
            csv.ReadHeader();
            List<string> csvColumns = csv.HeaderRecord.ToList() ?? new List<string>();
            if (csvColumns.Count == 0) 
            {
                MessageBox.Show("CSV file has no readable columns. Subsequent errors are to be expected.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

            // Get SQL column names for comparison
            List<string> sqlColumns = GetSQLColumns(sqlConnection, $"SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '{tableInputTextBox.Text}'");

            // Compare columns
            if (csvColumns.All(sqlColumns.Contains) && csvColumns.Count == sqlColumns.Count)
            {
                try
                {
                    sqlconn.Open();
                    using (SqlTransaction sqltrans = sqlconn.BeginTransaction())
                    using (SqlBulkCopy sqlcopy = new SqlBulkCopy(sqlconn, SqlBulkCopyOptions.KeepIdentity, sqltrans))
                    {
                        sqlcopy.DestinationTableName = tableInputTextBox.Text;
                        CsvDataReader csvdata = new CsvDataReader(csv);
                        sqlcopy.WriteToServer(csvdata);
                        sqltrans.Commit();
                    }
                    sqlconn.Close();
                }
                catch (Exception ex) 
                {
                    MessageBox.Show("An error occurred while writing the data: " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
            else
            {
                MessageBox.Show("Columns of the CSV file and columns of the SQL table do not match.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            
        }
    }
    else
    {
        MessageBox.Show("The file could not be read.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
}

static List<string> GetSQLColumns(string connectionString, string query) 
{
    List<string> columns = new List<string>();
    using (SqlConnection connection = new SqlConnection(connectionString))
    {
        SqlCommand command = new SqlCommand(query, connection);
        connection.Open();
        SqlDataReader reader = command.ExecuteReader();

        while (reader.Read())
        {
            columns.Add(reader["COLUMN_NAME"].ToString());
        }

        reader.Close();
        connection.Close();
    }
    return columns; 
}

CSV 文件的内容:

mitid; vname; nname; gehalt; geburtsdatum
5; bingus; bongus; 1223.23; 2010-01-01;
6; bongus; bingus; 1223.23; 2010-01-01;
c# sql-server csvhelper csvreader
1个回答
0
投票

如果您想创建一个返回 CsvReader 供以后使用的方法,则在将其返回给使用者之前无法关闭读取器实例。

更改此:

        var reader = new StreamReader(pathString);
        CsvReader csv = new CsvReader(reader, new CsvConfiguration(CultureInfo.InvariantCulture) { Delimiter = ";", HasHeaderRecord = true });
        reader.Close();
        return csv;

对此:

        var reader = new StreamReader(pathString);
        return new CsvReader(reader, new CsvConfiguration(CultureInfo.InvariantCulture) { Delimiter = ";", HasHeaderRecord = true });

请记住,您的设计可能不太理想。例如,您拥有的第二个 catch 块:

catch (Exception ex)
{
    MessageBox.Show("An error occurred while reading the CSV file: " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}

相当具有误导性,因为在此方法中您根本没有开始读取 CSV:您稍后在实际使用其外部的

CsvReader
实例时会这样做。

© www.soinside.com 2019 - 2024. All rights reserved.