簡體   English   中英

使用閱讀器將列輸入到csv文件中

[英]Using a reader to feed columns into a csv file

我有一個存儲過程,該過程將返回一列0或更多行或帳號。

如果有0行,我當然不需要做任何事情,但是如果返回1行或更多,則需要將這些帳號放入csv文件中。

返回的數據將如下所示:

100000
200000
286598

這是我的方法:

private static void ThirtyMinuteUpload(DateTime today)
{
    using (SqlConnection connection = new SqlConnection(connString))
    {
        using (SqlCommand command = new SqlCommand("mySP", connection))
        {
            command.CommandType = CommandType.StoredProcedure;

            connection.Open();
            if (command.ExecuteReader().HasRows)
            {
                // Create csv
            }
        }
    }
}

我需要將它們從我的閱讀器中放入csv中,並使用傳入的today變量將文件命名為:

exlcusion_mmddyyhhmmss.csv 

我從未使用過文件創建功能,現在可以將其保存到桌面上。 是容易做到的事情嗎?

我會做這樣的事情:

更新:修復了最后一個逗號問題。

using (SqlDataReader dr = command.ExecuteReader()) 
{
   if (dr.HasRows()) 
   {           
      string dateFormatted = today.ToString("MMddyyhhmmss");
      string path = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
      var writer = new StreamWriter(String.Format("{0}\exclusion_{1}.csv",
         path, dateFormatted);

      var cont = true;
      while (cont) 
      {
         // Grab the accountid before we read ahead
         var accId = dr["accountid"];

         // Read ahead to check if we've read the last record
         cont = dr.Read();

         // Last record, don't add comma
         if (!cont) 
         {
            writer.Write(accId); 
         }
         else 
         { 
            writer.Write(accId + ",");
         }
      }
   }
}
private static void ThirtyMinuteUpload(DateTime today)
{
    using (var cn = new SqlConnection(connString))
    using (var cmd = new SqlCommand("mySP", cn))
    {
        cmd.CommandType = CommandType.StoredProcedure;
        cn.Open();

        using (var rdr = cmd.ExecuteReader())
        {
            if (!rdr.HasRows) return;

            var fileName = string.Format("{0}{1}exclusion_{2:MMddyyHHmmss}.csv",
                Environment.GetFolderPath(Environment.SpecialFolder.Desktop),
                Path.PathSeparator,
                today);

            using (var writer = new StreamWriter(fileName))
            {
                while (rdr.Read())
                {
                    writer.WriteLine(rdr.GetString(0));
                }
            }
        }
    }
}

這是您問題的更抽象答案。 我沒有使用SqlDataReader ,而是編寫了一個通用函數,該函數將從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“標准”的文章

這個編寫者很幼稚-只是寫入從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);                
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM