Daten in eine CSV-Datei in C # schreiben

Ich versuche, eine csv Datei Zeile für Zeile in C # Sprache zu schreiben. Hier ist meine function

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

Die ganze function läuft innerhalb einer Schleife und jede Zeile sollte in die csv Datei geschrieben werden. In meinem Fall überschreibt die nächste Zeile die vorhandene Zeile und am Ende bekomme ich nur einen einzigen Datensatz in der CSV-Datei, die die letzte Zeile ist. Wie kann ich alle Zeilen in der csv Datei schreiben.

AKTUALISIEREN

In meinen naiven Tagen schlug ich vor, dies manuell zu machen (es war eine einfache Lösung für eine einfache Frage), aber aufgrund dessen, dass dies immer beliebter wird, würde ich empfehlen, die Bibliothek CsvHelper zu verwenden , die alle Sicherheitsüberprüfungen durchführt usw.

CSV ist viel komplizierter als das, was die Frage / Antwort vorschlägt.

Ursprüngliche Antwort

Da Sie bereits eine Schleife haben, sollten Sie folgendes tun:

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

Oder etwas in diesem Sinne. Meine Argumentation lautet: Sie müssen nicht für jedes Element in die Datei schreiben, Sie werden den Stream nur einmal öffnen und dann darauf schreiben.

Sie können ersetzen

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

mit

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

Wenn Sie frühere Versionen von CSV in derselben Datei behalten möchten

C # 6

Wenn Sie c # 6.0 verwenden, können Sie Folgendes tun

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

BEARBEITEN

Hier ist ein Link zu einer Frage, die erläutert, was Environment.NewLine tut

Ich würde Ihnen wärmstens empfehlen, die langweilige Route zu gehen. Vor allem, wenn Ihre Dateigröße groß ist.

 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() öffnet eine neue Datei, schreibt den Inhalt und schließt die Datei. Das Öffnen von Dateien ist eine sehr ressourcenintensive Operation, bei der Daten in den offenen Datenstrom geschrieben werden. Das Öffnen / Schließen einer Datei innerhalb einer Schleife führt zu einem performancesabfall.

Der Ansatz von Johan triggers dieses Problem, indem er die gesamte Ausgabe im Speicher speichert und sie dann einmal schreibt. Allerdings (im Fall von großen Dateien) wird Ihr Programm eine große Menge an RAM verbrauchen und sogar mit OutOfMemoryException

Ein weiterer Vorteil meiner Lösung besteht darin, dass Sie pausieren \ fortsetzen können, indem Sie die aktuelle Position in den Eingabedaten speichern.

upd. Platziert mit der richtigen Stelle

Das manuelle Schreiben von CSV-Dateien kann schwierig sein, da Ihre Daten Kommas und Zeilenumbrüche enthalten können. Ich schlage vor, dass Sie stattdessen eine vorhandene Bibliothek verwenden.

Diese Frage erwähnt einige Optionen.

Gibt es in C # CSV-Reader / Writer-Bibliotheken?

Ich verwende eine Zwei-Parse-Lösung, da sie sehr einfach zu warten ist

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

Verwenden Sie stattdessen einfach AppendAllText:

 File.AppendAllText(filePath, csv); 

Der einzige Nachteil des AppendAllText besteht darin, dass ein Fehler ausgegeben wird, wenn die Datei nicht existiert. Dies muss überprüft werden

Entschuldigung, blonder Moment, bevor ich die Dokumentation gelesen habe. Wie auch immer, die WriteAllText-Methode überschreibt alles, was zuvor in der Datei geschrieben wurde, wenn die Datei existiert.

Beachten Sie, dass Ihr aktueller Code keine richtigen neuen Zeilen verwendet, z. B. in Notepad wird alles als eine lange Zeile angezeigt. Ändern Sie den Code so, dass er die richtigen Zeilen enthält:

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

Anstatt jedes Mal AppendAllText() aufzurufen, AppendAllText() du einmal darüber nachdenken, die Datei zu öffnen und dann den gesamten Inhalt einmal zu schreiben:

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

Umgang mit Kommas

Für die Behandlung von Kommas innerhalb von Werten bei Verwendung von string.Format(...) hat Folgendes für mich funktioniert:

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

Um es mit Johans Antwort zu kombinieren, würde es so aussehen:

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

Rückgabe der CSV-Datei

Wenn Sie die Datei einfach zurückgeben möchten, anstatt sie an einen Ort zu schreiben, ist dies ein Beispiel dafür, wie ich sie erreicht habe:

Von einer gespeicherten Prozedur

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

Aus einer Liste

 /* To help illustrate */ public static List list = new List(); /* 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"); } 

Hoffentlich ist das hilfreich.

Anstatt das Rad neu zu erfinden, könnte eine Bibliothek verwendet werden. CsvHelper eignet sich hervorragend zum Erstellen und Lesen von CSV-Dateien. Die Lese- und Schreiboperationen sind streambasiert und unterstützen daher auch Operationen mit einer großen Datenmenge.


Sie können Ihre CSV wie folgt schreiben.

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

Da die Bibliothek Reflektionen verwendet, kann jeder Typ verwendet und direkt analysiert werden.

 public class CsvRow { public string Column1 { get; set; } public bool Column2 { get; set; } public CsvRow(string column1, bool column2) { Column1 = column1; Column2 = column2; } } IEnumerable 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); } 

Wert1, wahr

Wert2, falsch


Wenn Sie mehr über die Konfiguration und Möglichkeiten der Bibliotheken erfahren möchten, können Sie dies hier tun.

Sie müssen nur einen Zeilenvorschub "\n\r" hinzufügen.

Hier ist eine weitere Open-Source-Bibliothek zum einfachen Erstellen von CSV-Dateien, Cinchoo ETL

 List objs = new List(); 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); } 

Weitere Informationen finden Sie im CodeProject- Artikel zur Verwendung.

Dies ist ein einfaches Tutorial zum Erstellen von CSV-Dateien mit C #, das Sie bearbeiten und erweitern können, um es an Ihre eigenen Bedürfnisse anzupassen.

Zuerst müssen Sie eine neue Visual Studio C # -Konsolenanwendung erstellen. Hierzu sind die folgenden Schritte erforderlich.

Der Beispielcode erstellt eine CSV-Datei namens MyTest.csv an dem von Ihnen angegebenen Speicherort. Der Inhalt der Datei sollte 3 benannte Spalten mit Text in den ersten 3 Zeilen sein.

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

Eine einfache Möglichkeit, das Problem des Überschreibens zu File.AppendText , besteht darin, mit File.AppendText eine Zeile am Ende der Datei File.AppendText

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