我正在从SqlDataReader生成一个csv文件,但是它没有写出列名,我怎么能让它写出来?我正在使用的代码如下:
SqlConnection conn = new SqlConnection(myconn);
SqlCommand cmd = new SqlCommand("dbo.test", conn);
cmd.CommandType = CommandType.StoredProcedure;
conn.Open();
SqlDataReader reader = cmd.ExecuteReader();
StringBuilder sb = new StringBuilder();
StreamWriter sw = new StreamWriter(myfilePath + "testfile.csv");
while (reader.Read())
{
for (int i = 0; i < reader.FieldCount; i++)
{
string value = reader[i].ToString();
if (value.Contains(","))
value = "\"" + value + "\"";
sb.Append(value.Replace(Environment.NewLine, " ") + ",");
}
sb.Length--; // Remove the last comma
sb.AppendLine();
}
conn.Close();
sw.Write(sb.ToString());
sw.Close();
Run Code Online (Sandbox Code Playgroud)
读取所有列名称并将其附加到sb迭代读取器.
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())
....
Run Code Online (Sandbox Code Playgroud)
您可以使用SqlDataReader.GetName来获取列名称
for (int i = 0; i < reader.FieldCount; i++)
{
string columnName = reader.GetName(i);
}
Run Code Online (Sandbox Code Playgroud)
您还可以创建一个扩展方法,如下所示:
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;
}
Run Code Online (Sandbox Code Playgroud)
例子:
List<string> rows = null;
using (SqlDataReader dataReader = command.ExecuteReader())
{
rows = dataReader.ToCSV(includeHeadersAsFirstRow, separator);
dataReader.Close();
}
Run Code Online (Sandbox Code Playgroud)
使用这个解决方案 我创建了一个扩展。
/// <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());
}
Run Code Online (Sandbox Code Playgroud)