Gegevens in CSV-bestand schrijven in C#

Ik probeer rij voor rij in een csv-bestand te schrijven met behulp van de taal C#. Hier is mijn functie

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

De hele functie draait in een lus en elke rij moet naar het bestand csvworden geschreven. In mijn geval overschrijft de volgende rij de bestaande rij en uiteindelijk krijg ik maar één record in het csv-bestand dat het laatste is. Hoe kan ik alle rijen in het csv-bestand schrijven?


Antwoord 1, autoriteit 100%

UPDATE

In mijn naïeve dagen stelde ik voor dit handmatig te doen (het was een eenvoudige oplossing voor een simpele vraag), maar omdat dit steeds populairder wordt, raad ik aan om de bibliotheek CsvHelperdie alle veiligheidscontroles uitvoert, enz.

CSV is veel ingewikkelder dan wat de vraag/het antwoord suggereert.

Oorspronkelijk antwoord

Aangezien je al een lus hebt, overweeg dan om het als volgt te doen:

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

Of iets in die richting.
Mijn redenering is: je hoeft niet voor elk item naar het bestand te schrijven, je opent de stream maar één keer en schrijft er vervolgens naar.

U kunt vervangen

File.WriteAllText(filePath, csv.ToString());

met

File.AppendAllText(filePath, csv.ToString());

als u eerdere versies van csv in hetzelfde bestand wilt bewaren

C# 6

Als u c# 6.0 gebruikt, kunt u het volgende doen

var newLine = $"{first},{second}"

BEWERKEN

Hier is een linknaar een vraag die uitlegt wat Environment.NewLinewel.


Antwoord 2, autoriteit 29%

Ik zou je ten zeerste aanbevelen om de meer saaie route te nemen. Vooral als je bestandsgrootte groot is.

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()opent een nieuw bestand, schrijft de inhoud en sluit het bestand. Het openen van bestanden is een veel arbeidsintensievere operatie dan het schrijven van gegevens in open stream. Het openen/sluiten van een bestand in een lus leidt tot prestatieverlies.

De door Johan voorgestelde aanpak lost dat probleem op door alle uitvoer in het geheugen op te slaan en deze vervolgens eenmaal te schrijven. Echter (in het geval van grote bestanden) zal uw programma een grote hoeveelheid RAM verbruiken en zelfs crashen met OutOfMemoryException

Een ander voordeel van mijn oplossing is dat u pauzeren/hervatten kunt implementeren door de huidige positie op te slaan in invoergegevens.

op. Geplaatst met op de juiste plaats


Antwoord 3, autoriteit 10%

Het handmatig schrijven van csv-bestanden kan moeilijk zijn omdat uw gegevens komma’s en nieuwe regels kunnen bevatten. Ik raad u aan in plaats daarvan een bestaande bibliotheek te gebruiken.

Deze vraag noemt een paar opties.

Zijn er CSV-lezers/schrijversbibliotheken in C#?


Antwoord 4, autoriteit 5%

Ik gebruik een oplossing met twee ontledingen omdat het heel gemakkelijk te onderhouden is

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

Antwoord 5, autoriteit 4%

In plaats van elke keer AppendAllText()aan te roepen, zou je kunnen overwegen om het bestand één keer te openen en dan de hele inhoud één keer te schrijven:

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

Antwoord 6, autoriteit 4%

U kunt in plaats daarvan AppendAllTextgebruiken:

File.AppendAllText(filePath, csv);

Als de documentatie van WriteAllTextzegt:

Als het doelbestand al bestaat, wordt het overschreven

Houd er ook rekening mee dat uw huidige code niet de juiste nieuwe regels gebruikt, bijvoorbeeld in Kladblok ziet u het allemaal als één lange regel. Verander de code hierin om de juiste nieuwe regels te hebben:

string csv = string.Format("{0},{1}{2}", first, image, Environment.NewLine);

Antwoord 7, autoriteit 3%

In plaats van het wiel opnieuw uit te vinden, zou een bibliotheek kunnen worden gebruikt. CsvHelperis geweldig voor het maken en lezen van csv-bestanden. De lees- en schrijfbewerkingen zijn gebaseerd op streams en ondersteunen daarom ook bewerkingen met een grote hoeveelheid gegevens.


U kunt uw csv als volgt schrijven.

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

Omdat de bibliotheek reflectie gebruikt, zal het elk type nemen en het direct ontleden.

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

waarde1,waar

waarde2, onwaar


Als je meer wilt lezen over de configuraties en mogelijkheden van de bibliotheek, kun je dat hierdoen.


Antwoord 8, autoriteit 2%

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

Antwoord 9

Omgaan met komma’s

Voor het verwerken van komma’s binnen waarden bij het gebruik van string.Format(...), heeft het volgende voor mij gewerkt:

var newLine = string.Format("\"{0}\",\"{1}\",\"{2}\"",
                              first,
                              second,
                              third                                    
                              );
csv.AppendLine(newLine);

Dus om het te combineren met het antwoord van Johan, zou het er als volgt uitzien:

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

CSV-bestand retourneren

Als je het bestand gewoon wilt retourneren in plaats van het naar een locatie te schrijven, is dit een voorbeeld van hoe ik het heb gedaan:

Van een opgeslagen procedure

public FileContentResults DownloadCSV()
{
  // I have a stored procedure that queries the information I need
  SqlConnection thisConnection = new SqlConnection("Data Source=sv12sql;User ID=UI_Readonly;Password=SuperSecure;Initial Catalog=DB_Name;Integrated Security=false");
  SqlCommand queryCommand = new SqlCommand("spc_GetInfoINeed", thisConnection);
  queryCommand.CommandType = CommandType.StoredProcedure;
  StringBuilder sbRtn = new StringBuilder();
  // If you want headers for your file
  var header = string.Format("\"{0}\",\"{1}\",\"{2}\"",
                             "Name",
                             "Address",
                             "Phone Number"
                            );
  sbRtn.AppendLine(header);
  // Open Database Connection
  thisConnection.Open();
  using (SqlDataReader rdr = queryCommand.ExecuteReader())
  {
    while (rdr.Read())
    {
      // rdr["COLUMN NAME"].ToString();
      var queryResults = string.Format("\"{0}\",\"{1}\",\"{2}\"",
                                        rdr["Name"].ToString(),
                                        rdr["Address"}.ToString(),
                                        rdr["Phone Number"].ToString()
                                       );
      sbRtn.AppendLine(queryResults);
    }
  }
  thisConnection.Close();
  return File(new System.Text.UTF8Encoding().GetBytes(sbRtn.ToString()), "text/csv", "FileName.csv");
}

Uit een lijst

/* To help illustrate */
public static List<Person> list = new List<Person>();
/* To help illustrate */
public class Person
{
  public string name;
  public string address;
  public string phoneNumber;
}
/* The important part */
public FileContentResults DownloadCSV()
{
  StringBuilder sbRtn = new StringBuilder();
  // If you want headers for your file
  var header = string.Format("\"{0}\",\"{1}\",\"{2}\"",
                             "Name",
                             "Address",
                             "Phone Number"
                            );
  sbRtn.AppendLine(header);
  foreach (var item in list)
  {
      var listResults = string.Format("\"{0}\",\"{1}\",\"{2}\"",
                                        item.name,
                                        item.address,
                                        item.phoneNumber
                                       );
      sbRtn.AppendLine(listResults);
    }
  }
  return File(new System.Text.UTF8Encoding().GetBytes(sbRtn.ToString()), "text/csv", "FileName.csv");
}

Hopelijk is dit nuttig.


Antwoord 10

Dit is een eenvoudige tutorial over het maken van CSV-bestanden met C # waarmee u kunt bewerken en uitbreiden op uw eigen behoeften.

Eerst moet je een nieuwe visuele studio C # console-applicatie maken, er zijn stappen om dit te doen.

De voorbeeldcode maakt een CSV-bestand met de naam MyTest.CSV op de locatie die u opgeeft. De inhoud van het bestand moet 3 genoemde kolommen zijn met tekst in de eerste 3 rijen.

https: // Tidbytez.com/2018/02/06/how-to-create-a-csv-file-with-c/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace CreateCsv
{
    class Program
    {
        static void Main()
        {
            // Set the path and filename variable "path", filename being MyTest.csv in this example.
            // Change SomeGuy for your username.
            string path = @"C:\Users\SomeGuy\Desktop\MyTest.csv";
            // Set the variable "delimiter" to ", ".
            string delimiter = ", ";
            // This text is added only once to the file.
            if (!File.Exists(path))
            {
                // Create a file to write to.
                string createText = "Column 1 Name" + delimiter + "Column 2 Name" + delimiter + "Column 3 Name" + delimiter + Environment.NewLine;
                File.WriteAllText(path, createText);
            }
            // This text is always added, making the file longer over time
            // if it is not deleted.
            string appendText = "This is text for Column 1" + delimiter + "This is text for Column 2" + delimiter + "This is text for Column 3" + delimiter + Environment.NewLine;
            File.AppendAllText(path, appendText);
            // Open the file to read from.
            string readText = File.ReadAllText(path);
            Console.WriteLine(readText);
        }
    }
}

Antwoord 11

Misschien moet u gewoon een regelfeed toevoegen "\n\r".


Antwoord 12

Hier is nog een open source-bibliotheek om eenvoudig een CSV-bestand te maken, 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);
}

Lees voor meer informatie het artikel CodeProjectop gebruik.


Antwoord 13

Een eenvoudige manier om van het overschrijfprobleem af te komen, is door File.AppendTextte gebruiken om een regel aan het einde van het bestand toe te voegen als

void Main()
{
    using (System.IO.StreamWriter sw = System.IO.File.AppendText("file.txt"))
    {          
        string first = reader[0].ToString();
        string second=image.ToString();
        string csv = string.Format("{0},{1}\n", first, second);
        sw.WriteLine(csv);
    }
} 

Antwoord 14

enter code here

string string_value= string.Leeg;

       for (int i = 0; i < ur_grid.Rows.Count; i++)
        {
            for (int j = 0; j < ur_grid.Rows[i].Cells.Count; j++)
            {
                if (!string.IsNullOrEmpty(ur_grid.Rows[i].Cells[j].Text.ToString()))
                {
                    if (j > 0)
                        string_value= string_value+ "," + ur_grid.Rows[i].Cells[j].Text.ToString();
                    else
                    {
                        if (string.IsNullOrEmpty(string_value))
                            string_value= ur_grid.Rows[i].Cells[j].Text.ToString();
                        else
                            string_value= string_value+ Environment.NewLine + ur_grid.Rows[i].Cells[j].Text.ToString();
                    }
                }
            }
        }
        string where_to_save_file = @"d:\location\Files\sample.csv";
        File.WriteAllText(where_to_save_file, string_value);
        string server_path = "/site/Files/sample.csv";
        Response.ContentType = ContentType;
        Response.AppendHeader("Content-Disposition", "attachment; filename=" + Path.GetFileName(server_path));
        Response.WriteFile(server_path);
        Response.End();

Antwoord 15

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 WriteFields(this StreamWriter writer, params string[] fields) => WriteFields(writer, (IEnumerable<string>)fields);
}

Hiermee zou je heel eenvoudig een csv-bestand moeten kunnen schrijven. Gebruik:

StreamWriter writer = new StreamWriter("myfile.csv");
writer.WriteCSVLine(new[]{"A", "B"});

Other episodes