在C#中将数据写入CSV文件

ram*_*aaa 177 c# csv file

我试图csv使用C#语言逐行写入文件.这是我的功能

string first = reader[0].ToString();
string second=image.ToString();
string csv = string.Format("{0},{1}\n", first, second);
File.WriteAllText(filePath, csv);
Run Code Online (Sandbox Code Playgroud)

整个函数在循环内运行,每一行都应该写入csv文件.在我的情况下,下一行将覆盖现有行,最后,我在csv文件中获得了唯一一条记录,这是最后一行.如何写入csv文件中的所有行?

Joh*_*han 277

UPDATE

回到我天真的日子,我建议手动执行此操作(这是一个简单的问题的简单解决方案),但由于这变得越来越流行,我建议使用库CsvHelper执行所有安全检查等.

CSV比问题/答案所暗示的要复杂得多.

原始答案

因为你已经有了一个循环,所以考虑这样做:

//before your loop
    var csv = new StringBuilder();

//in your loop
    var first = reader[0].ToString();
    var second = image.ToString();
    //Suggestion made by KyleMit
    var newLine = string.Format("{0},{1}", first, second);
    csv.AppendLine(newLine);  

//after your loop
    File.WriteAllText(filePath, csv.ToString());
Run Code Online (Sandbox Code Playgroud)

或者是这种效果的东西.我的理由是:您不需要为每个项目写入文件,您只需打开一次流然后写入它.

你可以替换

File.WriteAllText(filePath, csv.ToString());
Run Code Online (Sandbox Code Playgroud)

File.AppendAllText(filePath, csv.ToString());
Run Code Online (Sandbox Code Playgroud)

如果你想在同一个文件中保留以前版本的csv

C#6

如果您使用的是c#6.0,则可以执行以下操作

var newLine = $"{first},{second}"
Run Code Online (Sandbox Code Playgroud)

编辑

这里是一个链接到一个问题,说明了什么Environment.NewLine

  • 当您的CSV内容有逗号需要转义时会发生什么?你需要报价.当报价需要逃避时会发生什么?正确构建CSV文件远比这个答案暗示的要复杂得多. (34认同)
  • 你也可以摆脱`{2}`和`Environment.NewLine`并使用`AppendLine`代替`Append` (4认同)
  • 你们都很高兴知道我已经更新了答案以正确的方式做事 (2认同)
  • 我已经尝试了您的解决方案,但是对我来说(法国文化),使用`System.Globalization.CultureInfo.CurrentCulture.TextInfo.ListSeparator`而不是逗号,效果更好。 (2认同)

Pav*_*gin 83

我强烈建议你走更繁琐的路线.特别是如果您的文件很大.

using(var w = new StreamWriter(path))
{
    for( /* your loop */)
    {
        var first = yourFnToGetFirst();
        var second = yourFnToGetSecond();
        var line = string.Format("{0},{1}", first, second);
        w.WriteLine(line);
        w.Flush();
    }
}
Run Code Online (Sandbox Code Playgroud)

File.AppendAllText()打开一个新文件,写入内容然后关闭文件.打开文件是一项耗费大量资源的操作,而不是将数据写入开放流.打开\关闭循环内的文件将导致性能下降.

Johan建议的方法通过将所有输出存储在内存中然后将其写入一次来解决该问题.但是(在大文件的情况下)你的程序将消耗大量的RAM甚至崩溃OutOfMemoryException

我的解决方案的另一个优点是您可以通过保存输入数据中的当前位置来实现暂停\恢复.

UPD.在正确的地方使用

  • 这个答案忽略了转义字符的必要性. (6认同)
  • 您应该将 for 循环放在“using”语句*内部*。否则,您将一次又一次地重新打开该文件。 (2认同)
  • 好答案.如果从格式字符串中删除"{2}"并在同一行中将"image"替换为"second",请更正正确答案.另外,不要忘记用w.Close()关闭作者; w.Flush()不需要. (2认同)

Jep*_*sen 27

手动编写csv文件可能很困难,因为您的数据可能包含逗号和换行符.我建议您使用现有的库.

这个问题提到了一些选择.

C#中是否有任何CSV读/写库?

  • 这是这里唯一合理正确的答案.令人遗憾的是,试图手工完成的其他糟糕答案有如此多的赞成. (4认同)

小智 16

我使用两个解析解决方案,因为它很容易维护

// Prepare the values
var allLines = (from trade in proposedTrades
                select new object[] 
                { 
                    trade.TradeType.ToString(), 
                    trade.AccountReference, 
                    trade.SecurityCodeType.ToString(), 
                    trade.SecurityCode, 
                    trade.ClientReference, 
                    trade.TradeCurrency, 
                    trade.AmountDenomination.ToString(), 
                    trade.Amount, 
                    trade.Units, 
                    trade.Percentage, 
                    trade.SettlementCurrency, 
                    trade.FOP, 
                    trade.ClientSettlementAccount, 
                    string.Format("\"{0}\"", trade.Notes),                             
                }).ToList();

// Build the file content
var csv = new StringBuilder();
allLines.ForEach(line => 
{
    csv.AppendLine(string.Join(",", line));            
});

File.WriteAllText(filePath, csv.ToString());
Run Code Online (Sandbox Code Playgroud)

  • 您可能会发现在构建大文件时使用此方法会遇到内存压力。如果删除 .ToList,则 allLines 将是 IEnumerbale<object[]>。然后,您可以选择它而不是“foreaching”,即 allines,Select(line => csv.AppendLine(string.Join(",", line))) ,这将为您提供 IEnumerable<string>。现在可以将其传递给 File,而不是 WriteAllLines 方法。现在这意味着整个事情都是懒惰的,您不需要将所有内容都拉入内存,但您仍然可以获得您满意的语法。 (2认同)

Sha*_*ard 9

只需使用AppendAllText:

File.AppendAllText(filePath, csv);
Run Code Online (Sandbox Code Playgroud)

AppendAllText的唯一缺点是当文件不存在时会抛出错误,因此必须检查

对不起,在阅读文档前的金发时刻.无论如何,如果文件存在,WriteAllText方法将覆盖先前在文件中写入的任何内容.

请注意,您当前的代码没有使用正确的新行,例如在记事本中,您将全部视为一条长行.将代码更改为具有适当的新行:

string csv = string.Format("{0},{1}{2}", first, image, Environment.NewLine);
Run Code Online (Sandbox Code Playgroud)

  • @Rajat不,这将在您的图像数据之后立即写入新的行字符. (2认同)

Oli*_*ver 7

而不是每次AppendAllText()都应该考虑打开文件一次,然后写一次整个内容:

var file = @"C:\myOutput.csv";

using (var stream = File.CreateText(file))
{
    for (int i = 0; i < reader.Count(); i++)
    {
        string first = reader[i].ToString();
        string second = image.ToString();
        string csvRow = string.Format("{0},{1}", first, second);

        stream.WriteLine(csvRow);
    }
}
Run Code Online (Sandbox Code Playgroud)


Ale*_*aro 7

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;
using System.Configuration;
using System.Data.SqlClient;

public partial class CS : System.Web.UI.Page
{
    protected void ExportCSV(object sender, EventArgs e)
    {
        string constr = ConfigurationManager.ConnectionStrings["constr"].ConnectionString;
        using (SqlConnection con = new SqlConnection(constr))
        {
            using (SqlCommand cmd = new SqlCommand("SELECT * FROM Customers"))
            {
                using (SqlDataAdapter sda = new SqlDataAdapter())
                {
                    cmd.Connection = con;
                    sda.SelectCommand = cmd;
                    using (DataTable dt = new DataTable())
                    {
                        sda.Fill(dt);

                        //Build the CSV file data as a Comma separated string.
                        string csv = string.Empty;

                        foreach (DataColumn column in dt.Columns)
                        {
                            //Add the Header row for CSV file.
                            csv += column.ColumnName + ',';
                        }

                        //Add new line.
                        csv += "\r\n";

                        foreach (DataRow row in dt.Rows)
                        {
                            foreach (DataColumn column in dt.Columns)
                            {
                                //Add the Data rows.
                                csv += row[column.ColumnName].ToString().Replace(",", ";") + ',';
                            }

                            //Add new line.
                            csv += "\r\n";
                        }

                        //Download the CSV file.
                        Response.Clear();
                        Response.Buffer = true;
                        Response.AddHeader("content-disposition", "attachment;filename=SqlExport.csv");
                        Response.Charset = "";
                        Response.ContentType = "application/text";
                        Response.Output.Write(csv);
                        Response.Flush();
                        Response.End();
                    }
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


NtF*_*reX 5

代替重新发明轮子,可以使用库。CsvHelper非常适合创建和读取csv文件。它的读取和写入操作基于流,因此也支持具有大量数据的操作。


您可以像下面这样编写csv。

using(var textWriter = new StreamWriter(@"C:\mypath\myfile.csv"))
{
    var writer = new CsvWriter(textWriter);
    writer.Configuration.Delimiter = ",";

    foreach (var item in list)
    {
        writer.WriteField( "a" );
        writer.WriteField( 2 );
        writer.WriteField( true );
        writer.NextRecord();
    }
}
Run Code Online (Sandbox Code Playgroud)

当库使用反射时,它将采用任何类型并直接解析。

public class CsvRow
{
    public string Column1 { get; set; }
    public bool Column2 { get; set; }

    public CsvRow(string column1, bool column2)
    {
        Column1 = column1;
        Column2 = column2;
    }
}

IEnumerable<CsvRow> rows = new [] {
    new CsvRow("value1", true),
    new CsvRow("value2", false)
};
using(var textWriter = new StreamWriter(@"C:\mypath\myfile.csv")
{
    var writer = new CsvWriter(textWriter);
    writer.Configuration.Delimiter = ",";
    writer.WriteRecords(rows);
}
Run Code Online (Sandbox Code Playgroud)

值1,真

值2,假


如果您想了解有关库配置和可能性的更多信息,可以在这里阅读