2010-02-21 11 views

Respuesta

14
  1. FileHelpers Biblioteca
  2. proveedor OLEDB de texto
  3. manual mediante la concatenación de cadenas de acuerdo con RFC-4180
  4. biblioteca de terceros, por ejemplo Aspose.Cells puede hacerlo sin ningún tipo de fricción de usted. Y es muy rápido.
+1

+1 para el enlace al RFC! También hay una buena referencia en Wikipedia: http://en.wikipedia.org/wiki/Comma-separated_values – TrueWill

8

Mire la biblioteca FileHelpers.

Desde el sitio:

The FileHelpers are a free and easy to use .NET library to import/export data from fixed length or delimited records in files, strings or streams.

Esto se asegurará de que todos los tipos de trampas de terminación de línea, tales escape y se maneja correctamente, según RFC-4180.

0

La elaboración de valores separados por comas siempre me gusta apuntar al método estático mucho subestimado string.Join(string separator, string[] elements), pero si hay librerías de ayuda por ahí, eso es probablemente mejor las cosas.

8

añadir el siguiente método para coche:

String Escape(String s) 
{ 
    StringBuilder sb = new StringBuilder(); 
    bool needQuotes = false; 
    foreach (char c in s.ToArray()) 
    { 
     switch (c) 
     { 
      case '"': sb.Append("\\\""); needQuotes = true; break; 
      case ' ': sb.Append(" "); needQuotes = true; break; 
      case ',': sb.Append(","); needQuotes = true; break; 
      case '\t': sb.Append("\\t"); needQuotes = true; break; 
      case '\n': sb.Append("\\n"); needQuotes = true; break; 
      default: sb.Append(c); break; 
     } 
    } 
    if (needQuotes) 
     return "\"" + sb.ToString() + "\""; 
    else 
     return sb.ToString(); 
} 

public void SerializeAsCsv(Stream stream) 
{ 
    stream.Write(Escape(Name)); 
    stream.Write(","); 
    stream.Write(Year.ToString()); 
    stream.Write(","); 
    stream.Write(Escape(Model)); 
    stream.Write("\n"); 
} 

ya se puede serializar toda la lista:

foreach (Car car in list) 
{ 
    car.SerializeAsCsv(stream); 
} 
0

me gustaría poner en práctica algunas conductas serialzation complementarias que según este article. Si quieres ser elegante, puedes crear una configuración en las propiedades de tus proyectos. Esta configuración determinaría si su clase usó csv o serialización predeterminada. A continuación, tendrá acceso a través de las técnicas que se muestran here. Considere usar un constructor estático para leer las aplicaciones y hacer que un valor booleano sea accesible para su código de serialización. El código de Vlads se ve genial, solo conéctelo a su código. También puede considerar otras formas, quizás más deseables, de cambiar su comportamiento de serialización.

O crear una interfaz llamada 'SerializeAsCSV' y utilizarlo algo así como esto:

// contenido parcial de MyCoolClass.csv:

public class MyCoolClass : ISerializeAsCSV, IDisposable 
    { 

     protected static bool serializesToCSV = false; 


     static MyCoolClass() 
     { 
     serializesToCSV = 
      (typeof(MyCoolClass).GetInterface("GrooveySoft.Shared.Interfaces.ISerializeAsCSV") == null) 
      ? false 
      : true; 

     } 


     public MyCoolClass(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) 
     { 
     // your stuff here 
     } 

     public void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) 
     { 
     // your stuff here 
     } 

    } 

// contenido de ISerializeAsCSV.cs

using System.Runtime.Serialization; 

namespace GrooveySoft.Shared.Interfaces 
{ 
    /// <summary> 
    /// indicates that implementor will serialize to csv format 
    /// </summary> 
    public interface ISerializeAsCSV : ISerializable 
    { 
    } 
} 

Esto debería comenzar. . . No he compilado y probado esto. . pero entiendes la idea general.

3

Estaba buscando una solución para esto, pero ninguna de las respuestas que encontré satisfizo mi unidad por simplicidad. Me di cuenta de que ya tenía la respuesta con mi código CRUD automático. Lo reutilicé y obtuve el siguiente código:

using System.Reflection; 
    /// <summary> 
    /// Using a bit of reflection to build up the strings. 
    /// </summary> 
    public static string ToCsvHeader(this object obj) 
    { 
     Type type = obj.GetType(); 
     var properties = type.GetProperties(BindingFlags.DeclaredOnly | 
             BindingFlags.Public | 
             BindingFlags.Instance); 

     string result = string.Empty; 
     Array.ForEach(properties, prop => 
     { 
      result += prop.Name + ","; 
     }); 

     return (!string.IsNullOrEmpty(result) ? result.Substring(0, result.Length - 1) : result); 
    } 

    public static string ToCsvRow(this object obj) 
    { 
     Type type = obj.GetType(); 
     var properties = type.GetProperties(BindingFlags.DeclaredOnly | 
             BindingFlags.Public | 
             BindingFlags.Instance); 

     string result = string.Empty; 
     Array.ForEach(properties, prop => 
     { 
      var value = prop.GetValue(obj, null); 
      var propertyType = prop.PropertyType.FullName; 
      if (propertyType == "System.String") 
      { 
       // wrap value incase of commas 
       value = "\"" + value + "\""; 
      } 

      result += value + ","; 

     }); 

     return (!string.IsNullOrEmpty(result) ? result.Substring(0, result.Length - 1) : result); 
    } 

Esto agregaría un método de extensión a cada objeto. El uso de la siguiente manera:

var burgers = new List<Cheeseburger>(); 
var output = burgers.ToCsvHeader(); 
output += Environment.NewLine; 

burgers.ForEach(burger => 
{ 
    output += burger.ToCsvRow(); 
    output += Environment.NewLine; 
}); 
var path = "[where ever you want]"; 
System.IO.File.WriteAllText(path, output); 

Hay probablemente una mejor manera de escribir estos dos métodos anteriores, pero esto funciona perfectamente para mi situación. Espero que ayude a alguien.

1

Usted podría simplemente reemplazar el método ToString o crear un método ToCSVRow() como tal

public String ToCSVRow() 
    { 
     return Name + "," + Year.ToString() + "," + Model; 
    } 

Y luego simplemente hacer algo como esto cuando sea necesario.

using (StreamWriter file = new StreamWriter(@"C:\Wherever\yourfilename.txt")) 
     { 
      foreach (var item in yourlist) 
      { 
       file.WriteLine(item.ToCSVRow()); 
      } 
     } 
Cuestiones relacionadas