private void WriteItem<T>(StreamWriter sr, T item)
{
string itemString = item.ToString();
if(itemString.IndexOfAny(new char[] { '"', ',', '\n', '\r' }) != -1)//skip test and always escape for different speed/filesize optimisation
{
sr.Write('"');
sr.Write(itemString.Replace("\"", "\"\""));
sr.Write('"');
}
else
sr.Write(itemString);
}
private void WriteLine<T>(StreamWriter sr, IEnumerable<T> line)
{
bool first = true;
foreach(T item in line)
{
if(!first)
sr.Write(',');
first = false;
WriteItem(sr, item);
}
}
private void WriteCSV<T>(StreamWriter sr, IEnumerable<IEnumerable<T>> allLines)
{
bool first = true;
foreach(IEnumerable<T> line in allLines)
{
if(!first)
sr.Write('\n');
first = false;
WriteLine(sr, line);
}
}
private void WriteCSV<T>(HttpResponse response, IEnumerable<IEnumerable<T>> allLines)
{
response.ContentType = "text/csv";
WriteCSV(response.Output, allLines);
}
Può valere anche l'invio di un'intestazione content-disposition con un nome file consigliato.
Modifica: Ultimamente, con i casi in cui è necessario interspazio un'azione tra gli elementi di un'enumerazione (come la virgola e la nuova riga sopra), ho preferito che piuttosto mantenendo un booleano che continua a essere controllato, gestisco l'enumeratore direttamente e quindi gestire il primo elemento separato dal resto. Ho iniziato a fare questo come un micro-opt in un push di efficienza, ma sono cresciuto fino a trovare solo un'espressione migliore di un percorso di codice che differisce per il primo elemento.Come tale, mi piacerebbe ora scrivo quanto sopra come:
private void WriteLine<T>(StreamWriter sr, IEnumerable<T> line)
{
using(var en = line.GetEnumerator())
if(en.MoveNext())
{
WriteItem(sr, en.Current);
while(en.MoveNext())
{
sr.Write(',');
WriteItem(sr, en.Current);
}
}
private void WriteCSV<T>(StreamWriter sr, IEnumerable<IEnumerable<T>> allLines)
{
using(var en = allLines.GetEnumerator())
if(en.MoveNext())
{
WriteLine(sr, en.Current);
while(en.MoveNext())
{
sr.Write('\n');
WriteLine(sr, en.Current);
}
}
}
fonte
2010-08-20 17:28:30
Dopo aver letto in giro. Tutto ciò di cui ho veramente bisogno è di eseguire il ciclo e generare i dati separati da virgole con/n alla fine della riga e continuare a scorrere fino al termine ... salvare il file come .csv e quindi chiudere lo stream ... corretto? – Tom
È inoltre necessario impostare il tipo di contenuto, e se un riferimento potrebbe contenere un carattere "", ',' o di nuova riga è necessario sfuggire anche a esso. Codice per quello nella mia risposta –