writeline write saving read example create and c# csv

c# - write - La forma más rápida de convertir una lista de objetos a csv con cada valor de objeto en una nueva línea



saving csv c# (6)

Debido a que la velocidad se mencionó en la pregunta, mi interés se centró en lo que podrían ser los rendimientos relativos y la rapidez con la que podría obtenerlo.

Sé que se excluyó StringBuilder, pero aún se sentía como el más rápido, y StreamWriter tiene la ventaja de escribir en un MemoryStream o directamente en un archivo, lo que lo hace versátil.

Así que hice una prueba rápida.

Construí una lista de medio millón de objetos idénticos a los suyos.

Luego serialicé con CsvSerializer, y con dos versiones ajustadas enrolladas a mano, una utilizando StreamWriter a MemoryStream y la otra utilizando StringBuilder.

El código enrollado a mano fue codificado para hacer frente a las citas, pero nada más sofisticado. Este código era bastante estricto con el mínimo que podía manejar de cuerdas intermedias, sin concatenación ... pero no producción y ciertamente no hay puntos por estilo o flexibilidad.

Pero la salida fue idéntica en los tres métodos.

Los tiempos fueron interesantes:

Serialización de medio millón de objetos, cinco ejecuciones con cada método, todos los tiempos al ms completo más cercano:

StringBuilder 703 734 828 671 718 Avge= 730.8 MemoryStream 812 937 874 890 906 Avge= 883.8 CsvSerializer 1,734 1,469 1,719 1,593 1,578 Avge= 1,618.6

Esto fue en un i7 de gama alta con un montón de RAM.

En igualdad de condiciones, siempre usaría la biblioteca.

Pero si una diferencia de rendimiento de 2: 1 se volvió crítica, o si la RAM u otros problemas resultaran exagerados en un conjunto de datos más grande, o si los datos llegasen en trozos y fueran enviados directamente al disco, podría ser tentado ...

En caso de que alguien esté interesado, el núcleo del código (para la versión StringBuilder) era

private void writeProperty(StringBuilder sb, string value, bool first, bool last) { if (! value.Contains(''/"'')) { if (!first) sb.Append('',''); sb.Append(value); if (last) sb.AppendLine(); } else { if (!first) sb.Append(",/""); else sb.Append(''/"''); sb.Append(value.Replace("/"", "/"/"")); if (last) sb.AppendLine("/""); else sb.Append(''/"''); } } private void writeItem(StringBuilder sb, Test item) { writeProperty(sb, item.Id.ToString(), true, false); writeProperty(sb, item.Name, false, false); writeProperty(sb, item.CreatedDate, false, false); writeProperty(sb, item.DueDate, false, false); writeProperty(sb, item.ReferenceNo, false, false); writeProperty(sb, item.Parent, false, true); }

Tengo una clase de la siguiente manera:

public class Test { public int Id {get;set;} public string Name { get; set; } public string CreatedDate {get;set;} public string DueDate { get; set; } public string ReferenceNo { get; set; } public string Parent { get; set; } }

y tengo una lista de objetos de prueba

List<Test>testobjs=new List();

Ahora me gustaría convertirlo en csv en el siguiente formato:

"1, John Grisham, 9/5 / 2014,9 / 5 / 2014,1356,0 / n2, Stephen King, 9/3 / 2014,9 / 9 / 2014,1367,0 / n3, The Rainmaker, 4 / 9 / 2014,18 / 9 / 2014,1 ";

Busqué "Convertir lista a csv c #" y obtuve las siguientes soluciones:

string.Join(",", list.Select(n => n.ToString()).ToArray())

Pero esto no pondrá el / n según sea necesario, es decir, para cada objeto

¿Hay alguna otra manera más rápida que la construcción de cadenas para hacer esto? Por favor ayuda...


Podría usar la biblioteca FileHelpers para convertir la lista de objetos a csv.

Considere el objeto dado, agregue el atributo DelimitedRecord a él.

[DelimitedRecord(",")] public class Test { public int Id {get;set;} public string Name { get; set; } public string CreatedDate {get;set;} public string DueDate { get; set; } public string ReferenceNo { get; set; } public string Parent { get; set; } }

Una vez que la lista está llena, (según la pregunta es testobjs)

var engine = new FileHelperEngine<Test>(); engine.HeaderText = engine.GetFileHeader(); string dirPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "//" + ConfigurationManager.AppSettings["MyPath"]; if (!Directory.Exists(dirPath)) { Directory.CreateDirectory(dirPath); } //File location, where the .csv goes and gets stored. string filePath = Path.Combine(dirPath, "MyTestFile_" + ".csv"); engine.WriteFile(filePath, testobjs);

Esto solo hará el trabajo por ti. Estuve usando esto para generar informes de datos por un tiempo hasta que cambié a Python.

PD: Demasiado tarde para responder, pero espero que esto ayude a alguien.


Su mejor opción sería utilizar una biblioteca existente. Le ahorra la molestia de resolverlo usted mismo y probablemente se ocupará de escapar caracteres especiales, agregar líneas de encabezado, etc. Puede usar el CSVSerializer de ServiceStack. Pero hay varios otros en nuget . La creación del CSV será tan fácil como la string csv = CsvSerializer.SerializeToCsv(testobjs);


Usa Cinchoo ETL

Install-Package ChoETL

o

Install-Package ChoETL.NETStandard

La muestra muestra cómo usarlo.

List<Test> list = new List<Test>(); list.Add(new Test { Id = 1, Name = "Tom" }); list.Add(new Test { Id = 2, Name = "Mark" }); using (var w = new ChoCSVWriter<Test>(Console.Out) .WithFirstLineHeader() ) { w.Write(list); }

Salida CSV:

Id,Name,CreatedDate,DueDate,ReferenceNo,Parent 1,Tom,,,, 2,Mark,,,,

Para más información, vaya a github.

https://github.com/Cinchoo/ChoETL


Utilice servicestack.text

Install-Package ServiceStack.Text

y luego use los métodos de extensión de cadena ToCsv(T)/FromCsv()

Ejemplos: https://github.com/ServiceStack/ServiceStack.Text

Actualización: Servicestack.Text ahora es gratis también en v4, que solía ser comercial. ¡Ya no es necesario especificar la versión! ¡Feliz serialización!

Actualización: Use ServiceStack.Text.Core para .NET Core.


LINQtoCSV es el más rápido y liviano que he encontrado y está disponible en GitHub. Le permite especificar opciones a través de atributos de propiedad.