DataReader to .CSV with column names

前端 未结 5 975
清酒与你
清酒与你 2020-12-15 10:49

I\'m generating a csv file from an SqlDataReader, however it is not writing the column names, how can I make it write them? The code I\'m using is as follows:



        
相关标签:
5条回答
  • 2020-12-15 11:06

    I developed following high performance extension

    static void Main(string[] args)
            {
                SqlConnection sqlCon = new SqlConnection("Removed");
                sqlCon.Open();
                SqlCommand sqlCmd = new SqlCommand("Select * from Table", sqlCon);
                SqlDataReader reader = sqlCmd.ExecuteReader();
                string csv=reader.ToCSVHighPerformance(true);
                File.WriteAllText("Test.CSV", csv);
                reader.Close();
                sqlCon.Close();
            }
    

    Extention:

    public static string ToCSVHighPerformance(this IDataReader dataReader, bool includeHeaderAsFirstRow = true,
                string separator = ",")
            {
                DataTable dataTable = new DataTable();
                StringBuilder csvRows = new StringBuilder();
                string row = "";
                int columns ;
                try
                {
                    dataTable.Load(dataReader);
                    columns= dataTable.Columns.Count;
                    //Create Header
                    if (includeHeaderAsFirstRow)
                    {
                        for (int index = 0; index < columns; index++)
                        {
                            row += (dataTable.Columns[index]);
                            if (index < columns - 1)
                                row += (separator);
                        }
                        row += (Environment.NewLine);
                    }
                    csvRows.Append(row);
    
                    //Create Rows
                    for (int rowIndex = 0; rowIndex < dataTable.Rows.Count; rowIndex++)
                    {
                        row = "";
                        //Row
                        for (int index = 0; index < columns - 1; index++)
                        {
                            string value = dataTable.Rows[rowIndex][index].ToString();
    
                            //If type of field is string
                            if (dataTable.Rows[rowIndex][index] is string)
                            {
                                //If double quotes are used in value, ensure each are replaced by double quotes.
                                if (value.IndexOf("\"") >= 0)
                                    value = value.Replace("\"", "\"\"");
    
                                //If separtor are is in value, ensure it is put in double quotes.
                                if (value.IndexOf(separator) >= 0)
                                    value = "\"" + value + "\"";
    
                                //If string contain new line character
                                while (value.Contains("\r"))
                                {
                                    value = value.Replace("\r", "");
                                }
                                while (value.Contains("\n"))
                                {
                                    value = value.Replace("\n", "");
                                }
                            }
                            row += value;
                            if (index < columns - 1)
                                row += separator;
                        }
                        dataTable.Rows[rowIndex][columns - 1].ToString().ToString().Replace(separator, " ");
                        row += Environment.NewLine;
                        csvRows.Append(row);
                    }
                }
                catch (Exception ex)
                {
                    throw ex;
                }
                return csvRows.ToString();
            }
    
    0 讨论(0)
  • 2020-12-15 11:13

    You can use the SqlDataReader.GetName method to get the name of a column, like this:

    for(int i = 0; i < reader.FieldCount; i++)
    {
        string columnName = reader.GetName(i);
    }
    
    0 讨论(0)
  • 2020-12-15 11:15

    Read all the column names and append it to sb then iterate reader.

    SqlDataReader reader = cmd.ExecuteReader();
    StringBuilder sb = new StringBuilder();
    
    //Get All column 
    var columnNames = Enumerable.Range(0, reader.FieldCount)
                            .Select(reader.GetName) //OR .Select("\""+  reader.GetName"\"") 
                            .ToList();
    
    //Create headers
    sb.Append(string.Join(",", columnNames));
    
    //Append Line
    sb.AppendLine();
    
    while (reader.Read())
    ....
    
    0 讨论(0)
  • 2020-12-15 11:16

    You can use SqlDataReader.GetName to get the column name

    for (int i = 0; i < reader.FieldCount; i++)
    {
        string columnName = reader.GetName(i);
    }
    

    Also you can create an extension method like below:

    public static List<string> ToCSV(this IDataReader dataReader, bool includeHeaderAsFirstRow, string separator)
    {
        List<string> csvRows = new List<string>();
        StringBuilder sb = null;
    
        if (includeHeaderAsFirstRow)
        {
            sb = new StringBuilder();
            for (int index = 0; index < dataReader.FieldCount; index++)
            {
                if (dataReader.GetName(index) != null)
                    sb.Append(dataReader.GetName(index));
    
                if (index < dataReader.FieldCount - 1)
                    sb.Append(separator);
            }
            csvRows.Add(sb.ToString());
        }
    
        while (dataReader.Read())
        {
            sb = new StringBuilder();
            for (int index = 0; index < dataReader.FieldCount - 1; index++)
            {
                if (!dataReader.IsDBNull(index))
                {
                    string value = dataReader.GetValue(index).ToString();
                    if (dataReader.GetFieldType(index) == typeof(String))
                    {
                        //If double quotes are used in value, ensure each are replaced but 2.
                        if (value.IndexOf("\"") >= 0)
                            value = value.Replace("\"", "\"\"");
    
                        //If separtor are is in value, ensure it is put in double quotes.
                        if (value.IndexOf(separator) >= 0)
                            value = "\"" + value + "\"";
                    }
                    sb.Append(value);
                }
    
                if (index < dataReader.FieldCount - 1)
                    sb.Append(separator);
            }
    
            if (!dataReader.IsDBNull(dataReader.FieldCount - 1))
                sb.Append(dataReader.GetValue(dataReader.FieldCount - 1).ToString().Replace(separator, " "));
    
            csvRows.Add(sb.ToString());
        }
        dataReader.Close();
        sb = null;
        return csvRows;
    }
    

    Example:

    List<string> rows = null;
    using (SqlDataReader dataReader = command.ExecuteReader())
        {
            rows = dataReader.ToCSV(includeHeadersAsFirstRow, separator);
            dataReader.Close();
        }
    
    0 讨论(0)
  • 2020-12-15 11:16

    Using this solution i created an extension.

    /// <summary>
    /// 
    /// </summary>
    /// <param name="reader"></param>
    /// <param name="filename"></param>
    /// <param name="path">if null/empty will use IO.Path.GetTempPath()</param>
    /// <param name="extension">will use csv by default</param>
    public static void ToCsv(this IDataReader reader, string filename, string path = null, string extension = "csv")
    {
        int nextResult = 0;
        do
        {
            var filePath = Path.Combine(string.IsNullOrEmpty(path) ? Path.GetTempPath() : path, string.Format("{0}.{1}", filename, extension));
            using (StreamWriter writer = new StreamWriter(filePath))
            {
                writer.WriteLine(string.Join(",", Enumerable.Range(0, reader.FieldCount).Select(reader.GetName).ToList()));
                int count = 0;
                while (reader.Read())
                {
                    writer.WriteLine(string.Join(",", Enumerable.Range(0, reader.FieldCount).Select(reader.GetValue).ToList()));
                    if (++count % 100 == 0)
                    {
                        writer.Flush();
                    }
                }
            }
    
            filename = string.Format("{0}-{1}", filename, ++nextResult);
        }
        while (reader.NextResult());
    }
    
    0 讨论(0)
提交回复
热议问题