Ecrire des données dans le fichier CSV en C#
j'essaie d'écrire dans un fichier csv
ligne par ligne en utilisant le langage C#. Voici ma fonction
string first = reader[0].ToString();
string second=image.ToString();
string csv = string.Format("{0},{1}n", first, second);
File.WriteAllText(filePath, csv);
toute la fonction s'exécute à l'intérieur d'une boucle, et chaque ligne doit être écrite dans le fichier csv
. Dans mon cas, la ligne suivante remplace la ligne existante et à la fin je suis seul enregistrement dans le fichier csv qui est la dernière. Comment puis-je écrire toutes les lignes dans le fichier csv
.
14 réponses
mise à JOUR
de retour à l'époque naïve, j'ai suggéré de le faire manuellement (c'était une solution simple à une question simple), mais en raison de cela de plus en plus populaire, je recommande d'utiliser la bibliothèque CsvHelper qui fait tous les contrôles de sécurité, etc.
CSV, c'est bien plus compliqué que ce que la question/réponse suggère.
Réponse Originale
comme vous avez déjà une boucle, envisagez de le faire comme ceci:
//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());
Ou quelque chose à cet effet. Mon raisonnement est le suivant: vous ne serez pas besoin d'écrire dans le fichier pour chaque élément, vous ne serez en ouvrant le flux une fois et puis l'écriture.
vous pouvez remplacer
File.WriteAllText(filePath, csv.ToString());
avec
File.AppendAllText(filePath, csv.ToString());
si vous voulez garder les versions précédentes de csv dans le même dossier
C# 6
si vous utilisez c# 6.0 alors vous pouvez faire ce qui suit""
var newLine = $"{first},{second}"
MODIFIER
voici un lien à une question qui explique ce que Environment.NewLine
fait
je vous recommande vivement de suivre la voie la plus fastidieuse. Surtout si la taille du fichier.
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()
ouvre un nouveau fichier, écrit le contenu, puis ferme le fichier. L'ouverture de fichiers est une opération qui nécessite beaucoup de ressources, plutôt que d'écrire des données dans open stream. Ouvrir\fermer un fichier à l'intérieur d'une boucle entraînera une baisse de performance.
L'approche suggérée par Johan résout ce problème en stockant toute la sortie en mémoire et puis écrire une fois. Cependant (dans le cas de gros fichiers) Votre programme consommera une grande quantité de RAM et même crash avec OutOfMemoryException
un autre avantage de ma solution est que vous pouvez implémenter l'arrêt\resuming en sauvegardant la position actuelle dans les données d'entrée.
upd. Placé en utilisant au bon endroit
écrire des fichiers csv à la main peut être difficile parce que vos données peuvent contenir des virgules et des nouvelles lignes. Je vous suggère d'utiliser une bibliothèque existante à la place.
cette question mentionne quelques options.
y a-t-il des bibliothèques de lecteurs/rédacteurs CSV dans C#?
j'utilise une solution à deux parties car c'est très facile à entretenir
// 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());
utilisez simplement Appendaltext à la place:
File.AppendAllText(filePath, csv);
le seul inconvénient de L'appendice textuel est qu'il va jeter l'erreur quand le fichier n'existe pas, ce qui doit être vérifié
Désolé, blonde moment avant de lire le documentation . Quoi qu'il en soit, la méthode WriteAllText annule tout ce qui a déjà été écrit dans le fichier, si le fichier existe.
notez que votre le code actuel n'utilise pas les nouvelles lignes appropriées, par exemple dans le bloc-notes vous verrez tout cela comme une longue ligne. Changer le code pour avoir de nouvelles lignes appropriées:
string csv = string.Format("{0},{1}{2}", first, image, Environment.NewLine);
au lieu d'appeler chaque fois AppendAllText()
vous devriez penser à ouvrir le fichier une fois et puis écrire le contenu entier une fois:
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();
}
}
}
}
}
}
au lieu de réinventer la roue, une bibliothèque pourrait être utilisée. CsvHelper
est grand pour la création et la lecture de fichiers csv. Ses opérations de lecture et d'écriture sont basées sur des flux et soutiennent donc aussi les opérations avec une grande quantité de données.
vous pouvez écrire votre csv comme suit.
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();
}
}
comme la bibliothèque utilise la réflexion, elle prendra n'importe quel type et le analysera directement.
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);
}
valeur1,véritable
valeur2,false
si vous souhaitez en savoir plus sur les configurations et les possibilités de librarys, vous pouvez le faire ici .
La Manipulation Des Virgules
pour la manipulation des virgules à l'intérieur des valeurs en utilisant string.Format(...)
, ce qui suit a fonctionné pour moi:
var newLine = string.Format("\"{0}\",\"{1}\",\"{2}\"",
first,
second,
third
);
csv.AppendLine(newLine);
donc pour le combiner avec la réponse de Johan, il ressemblerait à ceci:
//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());
fichier CSV de retour
Si vous voulais simplement retourner le fichier au lieu de l'écrire à un endroit, c'est un exemple de la façon dont j'ai accompli:
D'un procédé stocké
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");
}
D'une liste
/* 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");
}
J'espère que c'est utile.
vous pourriez juste avoir à ajouter une ligne d'alimentation "\n\r"
.
Voici une autre bibliothèque open source pour créer un fichier CSV facilement, 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);
}
pour plus d'information, veuillez lire l'article CodeProject sur l'utilisation.
il s'agit d'un simple tutoriel sur la création de fichiers csv en utilisant C# que vous pourrez éditer et développer pour répondre à vos propres besoins.
tout d'abord, vous aurez besoin de créer une nouvelle application Visual Studio C# console, il y a des étapes à suivre pour le faire.
le code d'exemple créera un fichier csv appelé MyTest.csv dans l'emplacement que vous spécifiez. Le contenu du fichier doit être composé de 3 colonnes nommées avec du texte dans les 3 premières lignes.
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);
}
}
}
une façon simple de se débarrasser de l'émission d'assurance est d'utiliser File.AppendText
pour ajouter la ligne à la fin du fichier comme
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);
}
}
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
}
}
}