2010-07-29 14 views
12

मैं सभी वर्ग उदाहरणों से सीएसवी बनाने का एक तरीका ढूंढ रहा हूं।जेनेरिक क्लास से सीएसवी (सभी गुण)

मुझे क्या चाहिए कि मैं किसी भी वर्ग (इसके सभी उदाहरण) को CSV में निर्यात कर सकता हूं।

क्या कुछ 1 मुझे इस के लिए संभावित समाधान के लिए निर्देशित कर सकते हैं (यदि पहले से ही परेशान हो)।

thanx!

+0

तो .. बस इसे लिखने? यह एक क्रमबद्ध प्रक्रिया है, लेकिन एक्सएमएल या बाइनरी के बजाय यह सीएसवी है। आपकी क्या समस्या हैं? –

+0

(ए) कक्षा के लिए एक उदाहरण दें, और (बी) आप जिस सीएसवी की अपेक्षा करते हैं उसके लिए एक उदाहरण दें, और आपको बहुत से जवाब मिलेगा कि कैसे (ए) से (बी) तक जाना है। –

+0

रेशमी: मैं इसे लिख सकता हूं, लेकिन मुझे कुछ जेनेरिक चाहिए, क्योंकि जब मैं कक्षाओं में गुण जोड़ रहा हूं तो मुझे सीएसवी के बारे में चिंता करने की ज़रूरत नहीं है .. डॉक्टर: उपयोगकर्ता (नाम, उपनाम, आयु ...) जैसे सरल डेटा वर्ग । मैं कुछ ऐसा सोच रहा था जैसे ";" स्टार्टर्स के लिए हेडर समेत सीमित। सरल कक्षाओं के लिए – no9

उत्तर

6

वास्तव में, कुछ इसी तरह यहां संबोधित किया गया है:

Best practices for serializing objects to a custom string format for use in an output file

आप को यह उपयोगी है?

एक नमूना है जो फ़ील्ड नामों और मानों को खींचने और उन्हें स्ट्रिंग में जोड़ने के लिए प्रतिबिंब का उपयोग करता है।

+0

यह ठीक दिखता है, मैंने एक्सटेंशन विधियों का कभी भी उपयोग नहीं किया:/ मैंने एक स्थैतिक वर्ग बनाया और मैंने आपके द्वारा जुड़े हुए हेजेंडॉर्फ़ में पोस्ट की गई विधियों को जोड़ा। अब मैं नहीं जानता कि सूची <> के तरीकों का विस्तार कैसे करें, इसलिए मैं कॉल कर सकता हूं। सूची के उदाहरण पर। टीसीएसवी को "उपयोगकर्ता" वर्ग कहने की अनुमति देता है ... – no9

1

आप सभी कक्षा गुणों/क्षेत्रों को पार करने के लिए reflection का उपयोग कर सकते हैं और उन्हें CSV पर लिख सकते हैं। एक बेहतर दृष्टिकोण एक कस्टम विशेषता को परिभाषित करना और उन सदस्यों को सजाने के लिए होगा जिन्हें आप निर्यात करना चाहते हैं और केवल उन विशेषताओं को निर्यात करें।

6

LINQ to CSV पर एक नज़र डालें। हालांकि यह भारी तरफ थोड़ा सा है, इसलिए मैंने निम्नलिखित कोड को केवल कार्यक्षमता के छोटे सबसेट को करने के लिए लिखा है जो मुझे चाहिए। यह गुण और फ़ील्ड दोनों को संभालता है, जैसे आपने पूछा, हालांकि और कुछ नहीं। एक चीज जो करता है वह आउटपुट से बच जाती है अगर इसमें कॉमा, कोट्स या न्यूलाइन कैरेक्टर होते हैं।

public static class CsvSerializer { 
    /// <summary> 
    /// Serialize objects to Comma Separated Value (CSV) format [1]. 
    /// 
    /// Rather than try to serialize arbitrarily complex types with this 
    /// function, it is better, given type A, to specify a new type, A'. 
    /// Have the constructor of A' accept an object of type A, then assign 
    /// the relevant values to appropriately named fields or properties on 
    /// the A' object. 
    /// 
    /// [1] http://tools.ietf.org/html/rfc4180 
    /// </summary> 
    public static void Serialize<T>(TextWriter output, IEnumerable<T> objects) { 
     var fields = 
      from mi in typeof (T).GetMembers(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static) 
      where new [] { MemberTypes.Field, MemberTypes.Property }.Contains(mi.MemberType) 
      let orderAttr = (ColumnOrderAttribute) Attribute.GetCustomAttribute(mi, typeof (ColumnOrderAttribute)) 
      orderby orderAttr == null ? int.MaxValue : orderAttr.Order, mi.Name 
      select mi; 
     output.WriteLine(QuoteRecord(fields.Select(f => f.Name))); 
     foreach (var record in objects) { 
      output.WriteLine(QuoteRecord(FormatObject(fields, record))); 
     } 
    } 

    static IEnumerable<string> FormatObject<T>(IEnumerable<MemberInfo> fields, T record) { 
     foreach (var field in fields) { 
      if (field is FieldInfo) { 
       var fi = (FieldInfo) field; 
       yield return Convert.ToString(fi.GetValue(record)); 
      } else if (field is PropertyInfo) { 
       var pi = (PropertyInfo) field; 
       yield return Convert.ToString(pi.GetValue(record, null)); 
      } else { 
       throw new Exception("Unhandled case."); 
      } 
     } 
    } 

    const string CsvSeparator = ","; 

    static string QuoteRecord(IEnumerable<string> record) { 
     return String.Join(CsvSeparator, record.Select(field => QuoteField(field)).ToArray()); 
    } 

    static string QuoteField(string field) { 
     if (String.IsNullOrEmpty(field)) { 
      return "\"\""; 
     } else if (field.Contains(CsvSeparator) || field.Contains("\"") || field.Contains("\r") || field.Contains("\n")) { 
      return String.Format("\"{0}\"", field.Replace("\"", "\"\"")); 
     } else { 
      return field; 
     } 
    } 

    [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)] 
    public class ColumnOrderAttribute : Attribute { 
     public int Order { get; private set; } 
     public ColumnOrderAttribute(int order) { Order = order; } 
    } 
} 
0

मैं दो वर्गों में मेरा उत्तर को अलग कर रहा हूँ: पहले एक कैसे एन्कोडिंग, हेडर के साथ, csv में कुछ सामान्य आइटम सूची निर्यात करने के लिए है - (यह केवल निर्दिष्ट हेडर के लिए csv डेटा का निर्माण होगा, और ध्यान नहीं देगा अनियंत्रित गुण)।

public string ExportCsv<T>(IEnumerable<T> items, Dictionary<string, string> headers) 
{ 
    string result; 
    using (TextWriter textWriter = new StreamWriter(myStream, myEncoding)) 
    { 
     result = this.WriteDataAsCsvWriter<T>(items, textWriter, headers); 
    } 
    return result; 
} 

private string WriteDataAsCsvWriter<T>(IEnumerable<T> items, TextWriter textWriter, Dictionary<string, string> headers) 
{ 
    //Add null validation 

    ////print the columns headers 
    StringBuilder sb = new StringBuilder(); 

    //Headers 
    foreach (KeyValuePair<string, string> kvp in headers) 
    { 
     sb.Append(ToCsv(kvp.Value)); 
     sb.Append(","); 
    } 
    sb.Remove(sb.Length - 1, 1);//the last ',' 
    sb.Append(Environment.NewLine); 

    //the values 
    foreach (var item in items) 
    { 
     try 
     { 
      Dictionary<string, string> values = GetPropertiesValues(item, headers); 

      foreach (var value in values) 
      { 
       sb.Append(ToCsv(value.Value)); 
       sb.Append(","); 
      } 
      sb.Remove(sb.Length - 1, 1);//the last ',' 
      sb.Append(Environment.NewLine); 
     } 
     catch (Exception e1) 
     { 
      //do something 
     } 
    } 
    textWriter.Write(sb.ToString()); 

    return sb.ToString(); 
} 

//Help function that encode text to csv: 
public static string ToCsv(string input) 
{ 
    if (input != null) 
    { 
     input = input.Replace("\r\n", string.Empty) 
      .Replace("\r", string.Empty) 
      .Replace("\n", string.Empty); 
     if (input.Contains("\"")) 
     { 
      input = input.Replace("\"", "\"\""); 
     } 

     input = "\"" + input + "\""; 
    } 

    return input; 
} 

यह सबसे महत्वपूर्ण कार्य है, इसके गुण निकालने (लगभग) किसी भी सामान्य वर्ग के बाहर महत्व देता है। GetPropertiesValues के लिए

private Dictionary<string, string> GetPropertiesValues(object item, Dictionary<string, string> headers) 
{ 
    Dictionary<string, string> values = new Dictionary<string, string>(); 
    if (item == null) 
    { 
     return values; 
    } 

    //We need to make sure each value is coordinated with the headers, empty string 
    foreach (var key in headers.Keys) 
    { 
     values[key] = String.Empty; 
    } 

    Type t = item.GetType(); 
    PropertyInfo[] propertiesInfo = t.GetProperties(); 

    foreach (PropertyInfo propertiyInfo in propertiesInfo) 
    { 
     //it not complex: string, int, bool, Enum 
     if ((propertiyInfo.PropertyType.Module.ScopeName == "CommonLanguageRuntimeLibrary") || propertiyInfo.PropertyType.IsEnum) 
     { 
      if (headers.ContainsKey(propertiyInfo.Name)) 
      { 
       var value = propertiyInfo.GetValue(item, null); 
       if (value != null) 
       { 
        values[propertiyInfo.Name] = value.ToString(); 
       }       
      } 
     } 
     else//It's complex property 
     { 
      if (propertiyInfo.GetIndexParameters().Length == 0) 
      { 
       Dictionary<string, string> lst = GetPropertiesValues(propertiyInfo.GetValue(item, null), headers); 
       foreach (var value in lst) 
       { 
        if (!string.IsNullOrEmpty(value.Value)) 
        { 
         values[value.Key] = value.Value; 
        } 
       } 
      } 
     } 
    } 
    return values; 
} 

उदाहरण:

public MyClass 
{ 
    public string Name {get; set;} 
    public MyEnum Type {get; set;} 
    public MyClass2 Child {get; set;} 
} 
public MyClass2 
{ 
    public int Age {get; set;} 
    public DateTime MyDate {get; set;} 
} 

MyClass myClass = new MyClass() 
{ 
    Name = "Bruce", 
    Type = MyEnum.Sometype, 
    Child = new MyClass2() 
    { 
     Age = 18, 
     MyDate = DateTime.Now() 
    } 
}; 

Dictionary<string, string> headers = new Dictionary<string, string>(); 
headers.Add("Name", "CustomCaption_Name"); 
headers.Add("Type", "CustomCaption_Type"); 
headers.Add("Age", "CustomCaption_Age"); 

GetPropertiesValues(myClass, headers)); // OUTPUT: {{"Name","Bruce"},{"Type","Sometype"},{"Age","18"}} 
संबंधित मुद्दे