c# - CsvHelper no escribe nada en el flujo de memoria
cvs helper c# (5)
Aquí está el ejemplo de trabajo:
void Main()
{
var records = new List<dynamic>{
new { Id = 1, Name = "one" },
new { Id = 2, Name = "two" },
};
Console.WriteLine(records.ToCsv());
}
public static class Extensions {
public static string ToCsv<T>(this IEnumerable<T> collection)
{
using (var memoryStream = new MemoryStream())
{
using (var streamWriter = new StreamWriter(memoryStream))
using (var csvWriter = new CsvWriter(streamWriter))
{
csvWriter.WriteRecords(collection);
} // StreamWriter gets flushed here.
return Encoding.ASCII.GetString(memoryStream.ToArray());
}
}
}
Basado en this respuesta.
Tengo el siguiente método:
public byte[] WriteCsvWithHeaderToMemory<T>(IEnumerable<T> records) where T : class
{
using (var memoryStream = new MemoryStream())
using (var streamWriter = new StreamWriter(memoryStream))
using (var csvWriter = new CsvWriter(streamWriter))
{
csvWriter.WriteRecords<T>(records);
return memoryStream.ToArray();
}
}
Que se llama con una lista de objetos, eventualmente desde una base de datos, pero como algo no funciona, simplemente estoy llenando una colección estática. Los objetos que se pasan son los siguientes:
using CsvHelper.Configuration;
namespace Application.Models.ViewModels
{
public class Model
{
[CsvField(Name = "Field 1", Ignore = false)]
public string Field1 { get; set; }
[CsvField(Name = "Statistic 1", Ignore = false)]
public int Stat1{ get; set; }
[CsvField(Name = "Statistic 2", Ignore = false)]
public int Stat2{ get; set; }
[CsvField(Name = "Statistic 3", Ignore = false)]
public int Stat3{ get; set; }
[CsvField(Name = "Statistic 4", Ignore = false)]
public int Stat4{ get; set; }
}
}
Lo que estoy tratando de hacer es escribir una colección en un csv para descargarla en una aplicación MVC. Sin embargo, cada vez que intento escribir en el método, MemoryStream vuelve con una longitud cero y no se le pasa nada. He usado esto antes, pero por alguna razón simplemente no funciona, estoy algo confundido. ¿Alguien puede señalarme lo que he hecho mal aquí?
Aclamaciones
No hay descarga en csvWriter, la descarga está en streamWriter. Cuando se llama
csvWriter.Dispose ();
se limpiará la corriente. Otro enfoque es establecer
streamWriter.AutoFlush = true;
que automáticamente descargará la corriente cada vez.
Ponga csvWriter.Flush();
Antes de volver a vaciar el escritor / stream.
EDIT: por la respuesta de Jack. Debe ser el flujo que se vacía, no el csvWriter. streamWriter.Flush();
. Dejando la solución original, pero añadiendo esta corrección.
Poniendo todo esto junto (y los comentarios para las correcciones), incluido el restablecimiento de la posición del flujo de memoria, la solución final para mí fue;
using (MemoryStream ms = new MemoryStream())
{
using (TextWriter tw = new StreamWriter(ms))
using (CsvWriter csv = new CsvWriter(tw))
{
csv.WriteRecords(errors); // Converts error records to CSV
tw.Flush(); // flush the buffered text to stream
ms.Seek(0, SeekOrigin.Begin); // reset stream position
Attachment a = new Attachment(ms, "errors.csv"); // Create attachment from the stream
// I sent an email here with the csv attached.
}
}
En caso de que el ayude a alguien mas!
Ya tienes un bloque de using
que es genial. Eso hará que tu escritor salga por ti. Solo puedes cambiar tu código ligeramente para que funcione.
using (var memoryStream = new MemoryStream())
{
using (var streamWriter = new StreamWriter(memoryStream))
using (var csvWriter = new CsvWriter(streamWriter))
{
csvWriter.WriteRecords<T>(records);
} // StreamWriter gets flushed here.
return memoryStream.ToArray();
}
Si AutoFlush
, debe tener cuidado. Esto se purgará después de cada escritura. Si su transmisión es una transmisión de red y por cable, será muy lenta.