Ich versuche, Zeile für Zeile in eine csv
-Datei mit C # -Sprache zu schreiben. Hier ist meine Funktion
string first = reader[0].ToString();
string second=image.ToString();
string csv = string.Format("{0},{1}\n", first, second);
File.WriteAllText(filePath, csv);
Die gesamte Funktion wird in einer Schleife ausgeführt 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, der letzte. Wie schreibe ich alle Zeilen in die csv
-Datei?
UPDATE
In meinen naiven Tagen schlug ich vor, dies manuell zu tun (es war eine einfache Lösung für eine einfache Frage), aber da dies immer beliebter wird, würde ich empfehlen, die Bibliothek CsvHelper zu verwenden, die alles tut die Sicherheitskontrollen usw.
CSV ist viel komplizierter als das, was die Frage/Antwort nahelegt.
Originalantwort
Da Sie bereits über eine Schleife verfügen, sollten Sie dies folgendermaßen 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 zu diesem Effekt ... Meine Begründung ist: Sie müssen nicht für jedes Element in die Datei schreiben, Sie werden den Stream nur einmal öffnen und dann 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}"
EDIT
Hier ist ein Link zu einer Frage, die erklärt, was Environment.NewLine
tut
Ich würde Ihnen wärmstens empfehlen, den etwas langwierigsten Weg zu gehen. Besonders 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 ein sehr ressourcenintensiver Vorgang als das Schreiben von Daten in den offenen Stream. Das Öffnen\Schließen einer Datei innerhalb einer Schleife führt zu Leistungseinbußen.
Der von Johan vorgeschlagene Ansatz löst dieses Problem, indem die gesamte Ausgabe im Speicher abgelegt und dann einmal geschrieben wird. (Bei großen Dateien) verbraucht Ihr Programm jedoch viel RAM und stürzt sogar mit OutOfMemoryException
ab.
Ein weiterer Vorteil meiner Lösung ist, dass Sie das Anhalten/Wiederaufnehmen implementieren können, indem Sie die aktuelle Position in den Eingabedaten speichern.
upd. Platziert an 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 nennt einige Möglichkeiten.
Ich verwende eine Zwei-Analyse-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 von AppendAllText besteht darin, dass ein Fehler ausgegeben wird, wenn die Datei nicht vorhanden ist. Daher muss dies geprüft werden
Sorry, blonder Moment, bevor Sie die Dokumentation lesen. In jedem Fall überschreibt die WriteAllText-Methode alles, was zuvor in die Datei geschrieben wurde, sofern die Datei vorhanden ist.
Beachten Sie, dass Ihr aktueller Code keine richtigen neuen Zeilen verwendet. In Notepad sehen Sie beispielsweise alles als eine lange Zeile. Ändern Sie den Code in dieses, um richtige neue Zeilen zu erhalten:
string csv = string.Format("{0},{1}{2}", first, image, Environment.NewLine);
Anstatt jedes Mal AppendAllText()
aufzurufen, sollten Sie die Datei einmal öffnen und dann den gesamten Inhalt einmal 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();
}
}
}
}
}
}
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 basieren auf Streams 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 die Reflektion verwendet, nimmt sie jeden Typ und analysiert sie direkt.
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);
}
wert1, wahr
value2, false
Wenn Sie mehr über die Konfigurationen und Möglichkeiten der Bibliotheken erfahren möchten, können Sie dies tun hier .
Beim Umgang mit Kommas innerhalb von Werten bei Verwendung von string.Format(...)
hat sich Folgendes für mich bewährt:
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());
Wenn Sie die Datei einfach zurückgeben möchten, anstatt sie an einen Speicherort zu schreiben, ist dies ein Beispiel, wie ich sie erreicht habe:
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");
}
/* 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");
}
Hoffentlich ist das hilfreich.
Hier ist eine weitere Open Source-Bibliothek zum einfachen Erstellen von CSV-Dateien. 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);
}
Weitere Informationen finden Sie im Artikel CodeProject 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.
Zunächst müssen Sie eine neue Visual Studio C # -Konsolenanwendung erstellen. Dazu müssen Sie folgende Schritte ausführen.
Der Beispielcode erstellt eine CSV-Datei mit dem Namen MyTest.csv am angegebenen Speicherort. Der Inhalt der Datei sollte 3 benannte Spalten mit Text in den ersten 3 Zeilen sein.
https://tidbytez.com/2018/02/06/wie-zu-erstellen-a-csv-datei-mit-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);
}
}
}
Sie müssen möglicherweise nur einen Zeilenvorschub "\n\r"
hinzufügen.
public void UlozCSV()
{
using (StreamWriter pisar = new StreamWriter("zbozi.csv", false, Encoding.Default))
{// u ukládání nezapomenout - za názvem je FALSE
pisar.WriteLine(hlavicka); //první řešíme hlavičku csv a následně vypisujeme jednotlivé reproduktory
foreach (Reproduktor item in list)
{
pisar.WriteLine(item.ObjektNaCSVRadek()); //metoda která vypíše podle své třídy
}
}
}
Eine einfache Möglichkeit, das Überschreibungsproblem zu beseitigen, besteht darin, mit File.AppendText
eine Zeile am Ende der Datei als anzufügen
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);
}
}