我试图用c#语言一行一行地写入csv文件。这是我的函数

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

整个函数在循环中运行,每一行都应该写入csv文件。在我的例子中,下一行覆盖了现有的行,最后,我在csv文件中只得到一条记录,这是最后一条记录。如何写入csv文件中的所有行?


当前回答

下面是另一个开源库,可以轻松创建CSV文件,Cinchoo ETL

List<dynamic> objs = new List<dynamic>();

dynamic rec1 = new ExpandoObject();
rec1.Id = 10;
rec1.Name = @"Mark";
rec1.JoinedDate = new DateTime(2001, 2, 2);
rec1.IsActive = true;
rec1.Salary = new ChoCurrency(100000);
objs.Add(rec1);

dynamic rec2 = new ExpandoObject();
rec2.Id = 200;
rec2.Name = "Tom";
rec2.JoinedDate = new DateTime(1990, 10, 23);
rec2.IsActive = false;
rec2.Salary = new ChoCurrency(150000);
objs.Add(rec2);

using (var parser = new ChoCSVWriter("emp.csv").WithFirstLineHeader())
{
    parser.Write(objs);
}

有关更多信息,请阅读CodeProject关于使用的文章。

其他回答

你可以使用AppendAllText代替:

File.AppendAllText(filePath, csv);

正如WriteAllText的文档所说:

如果目标文件已经存在,那么它将被覆盖

此外,请注意您当前的代码没有使用适当的新行,例如在记事本中,您将看到它都是一个长行。将代码更改为这样,以获得正确的新行:

string csv = string.Format("{0},{1}{2}", first, image, Environment.NewLine);
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();
                    }
                }
            }
        }
    }
}

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


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

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

    foreach (var item in list)
    {
        writer.WriteField( "a" );
        writer.WriteField( 2 );
        writer.WriteField( true );
        writer.NextRecord();
    }
}

由于库正在使用反射,它将接受任何类型并直接解析它。

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, CultureInfo.InvariantCulture);
    writer.Configuration.Delimiter = ",";
    writer.WriteRecords(rows);
}

value1,真切

value2,假


如果你想阅读更多关于库的配置和可能性,你可以在这里这样做。

我强烈建议你走更乏味的路线。尤其是当你的文件很大的时候。

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();
    }
}

file. appendalltext()打开一个新文件,写入内容,然后关闭文件。与将数据写入开放流相比,打开文件是一个耗费大量资源的操作。在循环中打开/关闭文件会导致性能下降。

Johan建议的方法解决了这个问题,方法是将所有输出存储在内存中,然后只写入一次。然而(在大文件的情况下),您的程序将消耗大量的RAM,甚至崩溃与OutOfMemoryException

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

乌利希期刊指南。把使用放在正确的地方

public static class Extensions
{
    public static void WriteCSVLine(this StreamWriter writer, IEnumerable<string> fields)
    {
        const string q = @"""";
        writer.WriteLine(string.Join(",",
            fields.Select(
                v => (v.Contains(',') || v.Contains('"') || v.Contains('\n') || v.Contains('\r')) ? $"{q}{v.Replace(q, q + q)}{q}" : v
                )));
    }

    public static void WriteCSVLine(this StreamWriter writer, params string[] fields) => WriteCSVLine(writer, (IEnumerable<string>)fields);
}

这将允许您非常简单地编写csv文件。用法:

StreamWriter writer = new ("myfile.csv");
writer.WriteCSVLine("A", "B"); // A,B