Jeg prøver å skrive inn i en csv
fil rad for rad ved hjelp av C # språk. Her er funksjonen min
string first = reader[0].ToString();
string second=image.ToString();
string csv = string.Format("{0},{1}\n", first, second);
File.WriteAllText(filePath, csv);
Hele funksjonen kjører inne i en løkke, og hver rad skal skrives til csv
-filen. I mitt tilfelle overskriver neste rad den eksisterende raden, og til slutt får jeg bare en enkelt post i csv-filen som er den siste. Hvordan kan jeg skrive alle radene i csv-filen?
OPPDATERING
Tilbake i mine naïve dager foreslo jeg å gjøre dette manuelt (det var en enkel løsning på et enkelt spørsmål), men på grunn av at dette blir mer og mer populært, vil jeg anbefale å bruke biblioteket CsvHelper som gjør alle sikkerhetskontroller osv.
CSV er mye mer komplisert enn hva spørsmålet / svaret antyder.
Originalt svar
Siden du allerede har en sløyfe, kan du vurdere å gjøre det slik:
//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());
Eller noe i denne retningen. Resonnementet mitt er: du trenger ikke å skrive til filen for hvert element, du vil bare åpne strømmen en gang og deretter skrive til den.
Du kan erstatte
File.WriteAllText(filePath, csv.ToString());
med
File.AppendAllText(filePath, csv.ToString());
hvis du vil beholde tidligere versjoner av csv i samme fil
C# 6
Hvis du bruker c# 6.0, kan du gjøre følgende
var newLine = $"{first},{second}"
EDIT
Her er en lenke til et spørsmål som forklarer hva Environment.NewLine
gjør
Jeg vil på det sterkeste anbefale deg å gå den mer omstendelige ruten. Spesielt hvis filstørrelsen din er stor.
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()
åpner en ny fil, skriver innholdet og lukker deretter filen. Å åpne filer er en mye mer ressurskrevende operasjon enn å skrive data i en åpen strøm. Åpning\lukking av en fil inne i en løkke vil føre til redusert ytelse.
Tilnærmingen foreslått av Johan løser dette problemet ved å lagre all utdata i minnet og deretter skrive den én gang. Imidlertid (i tilfelle store filer) vil programmet forbruke en stor mengde RAM og til og med krasje med OutOfMemoryException
.
En annen fordel med løsningen min er at du kan implementere pause \ gjenoppta ved å lagre gjeldende posisjon i inndata.
upd. Plassert ved hjelp av på riktig sted
Bare bruk AppendAllText i stedet:
File.AppendAllText(filePath, csv);
Den eneste ulempen med AppendAllText er at den vil kaste feil når filen ikke finnes, så dette må kontrolleres
Beklager, blondt øyeblikk før jeg leste dokumentasjonen. Uansett, WriteAllText-metoden overskriver alt som tidligere ble skrevet i filen, hvis filen eksisterer.
Legg merke til at den nåværende koden din ikke bruker riktige nye linjer, for eksempel i Notisblokk vil du se alt som en lang linje. Endre koden til dette for å få riktige nye linjer:
string csv = string.Format("{0},{1}{2}", first, image, Environment.NewLine);