2010-02-21 31 views
18

如果我有一個名爲「汽車」的對象的列表:如何將對象列表轉換爲csv?

public class Car 
{ 
    public string Name; 
    public int Year; 
    public string Model; 
} 

如何轉換對象,例如列表列表<汽車>到csv?

+0

你能轉換嗎?你試過了哪一個? – Praveen 2013-05-07 09:04:42

回答

14
  1. FileHelpers圖書館
  2. 文本OLEDB提供
  3. 通過字符串連接根據RFC-4180
  4. 第三方庫手冊,例如Aspose.Cells可以不用你的任何摩擦。而且很快很快
+1

+1鏈接到RFC! Wikipedia上還有一個很好的參考資料:http://en.wikipedia.org/wiki/Comma-separated_values – TrueWill 2010-02-21 17:29:12

8

看看FileHelpers庫。

從網站:

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.

這將確保各類在線路終端陷阱的,逃逸,這樣的正確處理,按照RFC-4180

0

將逗號分隔的值放在一起我總是喜歡指向被低估的string.Join(string separator, string[] elements)靜態方法,但是如果有輔助類庫,那可能是更好的東西。

8

以下方法添加到車:

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"); 
} 

現在可以序列整個列表:

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

我要實現一些addtional serialzation行爲按本article。如果你想要看起來,你可以在你的項目屬性中創建一個設置。此設置將確定您的類是否使用csv或默認的序列化。然後您可以通過here所示的技術訪問它。考慮使用靜態構造函數來讀取appsettings併爲您的序列化代碼創建一個布爾值。 Vlads的代碼看起來很棒,只需將其插入代碼即可。你也可以考慮其他的,也許更可取的方法來改變你的序列化行爲。

,或者創建所謂的 'SerializeAsCSV' 的接口,並使用它有點像這樣: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 
     } 

    } 

// ISerializeAsCSV.cs內容

using System.Runtime.Serialization; 

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

這應該讓你開始。 。 。我沒有編譯和測試這個。 。但你得到了一般想法。

3

我正在爲此尋找一個解決方案,但沒有一個我發現的答案滿足了我的驅動器的簡單性。我意識到我已經有了我的自動CRUD代碼的答案。我改變了它,並提出了以下代碼:

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); 
    } 

這將爲每個對象添加一個擴展方法。像這樣的用法:

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); 

上面寫這兩種方法可能有更好的方法,但這對我的情況完全適用。希望它能幫助別人。

1

你可以簡單地重寫ToString方法,或創建ToCSVRow()方法,這樣

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

然後就是做這樣的事情在需要的地方。

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