這裏是一個更抽象的回答你的問題。我寫了一個通用函數,用於將任何System.Data.IDataReader
(System.Data.SqlClient.SqlDataReader
只是一個類)的實現者的數據寫入任何System.IO.Stream
,其中包括文件(使用FileStream
)。
/// <summary>
/// Writes the data from a given <see cref="IDataReader"/> <paramref name="reader"/> to the <paramref name="output"/> <see cref="Stream"/>.
/// There are optional parameters for writing a header, specifying the encoding, the buffer size, and whether or not the stream should be
/// closed when we're done reading.
/// </summary>
/// <param name="reader">Any object which implements <see cref="IDataReader"/>-- most likely a <see cref="System.Data.SqlClient.SqlDataReader"/>.</param>
/// <param name="output">The stream to output the CSV contents to.</param>
/// <param name="writeHeader">When true, a header is written using the column names.</param>
/// <param name="encoding">Optional parameter (defaulting to UTF8 without BOM) denoting how the data should be encoded.</param>
/// <param name="bufferSize">Optional parameter (defaulting to 1KB) which is used as a buffer for writing the data.</param>
/// <param name="closeOutput">Optional parameter which, when true, closes the <paramref name="output"/> <see cref="Stream"/> after we're doing writing.</param>
private static void WriteCsv(IDataReader reader, Stream output, bool writeHeader = true, Encoding encoding = null, int bufferSize = 1024, bool closeOutput = false)
{
// If no encoding is provided, use the same one the StreamWriter defaults to.
if (encoding == null)
encoding = new UTF8Encoding(false, true);
// Create a new writer to our CSV file.
using (var writer = new StreamWriter(output, encoding, bufferSize, !closeOutput))
{
// This will create an enumerable with every integer between 0 and FieldCount-1.
// Allows us to do a concise for loop and use String.Join to handle the comma placement.
var indices = Enumerable.Range(0, reader.FieldCount);
// Keep looping as long as their are rows returned by the reader.
while (reader.Read())
{
// Write a header with the names of each column.
if (writeHeader)
{
writer.WriteLine(String.Join(",", indices.Select(i => reader.GetName(i) ?? ("column" + i))));
writeHeader = false;
}
// Write the value of each field by its string representation separated by a comma.
writer.WriteLine(String.Join(",", indices.Select(i => (reader.IsDBNull(i) ? null : reader.GetString(i)) ?? "")));
}
}
}
此功能讓你喜歡的編碼和什麼樣的你寫流的一些具體的控制大量(你可以寫一個HTTP響應或常規文件中,無所謂) 。如果您想要將更復雜的數據輸出到CSV文件中,我建議您通過CSV「標準」閱讀this article。
這位作家是天真的 - 它只是寫入從IDataReader
讀取的原始數據。如果您的內容有換行符,回車符或逗號,它可能會混淆最終消耗程序輸出的任何內容。我會編寫一個CsvEncode
函數,您可以將每個值輸入,並根據上面的文章中列出的規則對其進行正確編碼。
這只是一個例子,而不是代碼,實際上應該使用:
private static string CsvEncode(string value)
{
// Handle commas within values.
if (value.Contains(','))
{
// Strim so we get rid of beginning and trailing whitespaces we'd usually ignore.
value = value.Trim();
// If the value is already wrapped with quotation marks but has quotation marks within as well,
if (value.StartsWith("\"") && value.EndsWith("\"") && value.IndexOf('\"', 1, value.Length-2) > 0)
value = "\"" + value.Substring(1, value.Length - 2).Replace("\"", "\"\"") + "\"";
else if (value.Contains("\"")) // Replace all quotations with two quotations, then wrap the final result.
value = "\"" + value.Replace("\"", "\"\"") + "\"";
}
return value;
}
而你也只需更新WriteCsv
所以當它寫行的值,你調用CsvEncode
,類似(只是舉個例子):
// Write the value of each field by its string representation separated by a comma.
writer.WriteLine(String.Join(",", indices.Select(i => CsvEncode(reader.IsDBNull(i) ? "" : reader.GetString(i) ?? ""))));
而只是爲了要徹底,這是你會怎麼稱呼它:
using (var reader = command.ExecuteReader())
{
if (!reader.HasRows)
return; // Nothing to do.
// You want it on the desktop? We'll put it on the desktop.
var filePath = string.Format("{0}{1}exclusion_{2:MMddyyHHmmss}.csv",
Environment.GetFolderPath(Environment.SpecialFolder.Desktop),
Path.PathSeparator,
today);
// Pass in the reader we got from executing the command. File.Create will replace any
// existing files. closeOutput is true because we do not keep a reference to the FileStream.
WriteCsv(reader, File.Create(filePath), closeOutput: true);
}
你除了什麼類型的輸出?全部在一行(例A1:1000,B1:2000,C13000等)或全部在一列(A1:1000,A2:2000,A3:3000等等)? – Tinwor