2014-12-01 137 views
-1

這是我遇到的一個相當簡單的問題,但我的知識非常有限。我有一個將現有數據庫變成CSV的程序;但是,許多字段都包含逗號,我需要它們才能逃脫。我已經嘗試了一些無用的東西(在ObjectToCsvData下),所以任何與包含片段的幫助將不勝感激。逗號在stringbuilder中逃脫

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Collections; 
using System.Reflection; 

namespace OfaSort 
{ 
public static class Utility 
{ 
    public static string CollectionToCsv(IList collection) 
    { 
     StringBuilder sb = new StringBuilder(); 

      for (int index = 0; index < collection.Count; index++) 
      { 
      object item = collection[index]; 

      if (index == 0) 
      { 
       sb.Append(ObjectToCsvHeader(item)); 
      } 
      sb.Append(ObjectToCsvData(item)); 
      sb.Append(Environment.NewLine); 
     } 

     return sb.ToString(); 
    } 

    public static string ObjectToCsvData(object obj) 
    { 
     /*if (obj == null) 
     { 
      throw new ArgumentNullException("obj", "value is null"); 
     }*/ 
     StringBuilder sb = new StringBuilder(); 

     Type t = obj.GetType(); 
     PropertyInfo[] pi = t.GetProperties(); 
     for (int index = 0; index < pi.Length; index++) 
     { 
      /*object oTest = pi[index].GetValue(obj, null); 
      string str = oTest.ToString(); 
      sb.Append(str.CsvQuote()); 
      */ 
      sb.Append(pi[index].GetValue(obj, null));   
      if (index < pi.Length - 1) 
      { 
       sb.Append(","); 
      } 
     } 

     return sb.ToString(); 

} 

    public static string ObjectToCsvHeader(object obj) 
    { 

     /*if (obj == null) 
     { 
      throw new ArgumentNullException("obj", "value is null!"); 
     }*/ 

     StringBuilder sb = new StringBuilder(); 
     Type t = obj.GetType(); 
     PropertyInfo[] pi = t.GetProperties(); 

     for (int index = 0; index < pi.Length; index++) 
     { 
      sb.Append(pi[index].Name); 

      if (index < pi.Length - 1) 
      { 
       sb.Append(","); 
      } 
     } 
     sb.Append(Environment.NewLine); 

     return sb.ToString(); 
    } 

public static string CsvQuote(this string text) 
{ 
    if (text == null) 
    { 
     return string.Empty; 
    } 

    bool containsQuote = false; 
    bool containsComma = false; 
    int len = text.Length; 
    for (int i = 0; i < len && (containsComma == false || containsQuote == false); i++) 
    { 
     char ch = text[i]; 
     if (ch == '"') 
     { 
      containsQuote = true; 
     } 
     else if (ch == ',') 
     { 
      containsComma = true; 
     } 
    } 

    bool mustQuote = containsComma || containsQuote; 

    if (containsQuote) 
    { 
     text = text.Replace("\"", "\"\""); 
    } 

    if (mustQuote) 
    { 
     return "\"" + text + "\""; 
    } 
    else 
    { 
     return text; 
    } 
} 

} 

}

+0

簡單的測試:__if((VAL包含',')||(VAL包含' 「'))__渦卷值在'」'和逃逸的任何現有'「' (如''「') – 2014-12-01 21:46:35

+3

1.問題在哪裏?2.不要編寫自己的CSV編寫器或解析器,這裏有_many_工作庫/ nugets – Mormegil 2014-12-01 21:48:08

+0

您的containsQuote /逗號代碼可以替換爲'containsQuote = text.IndexOf(''')> = 0; containsComma = text.IndexOf(',')> = 0;'。 – 2014-12-01 21:55:37

回答

0
public static class CsvUtility 
{ 
    // I'm varying this a bit because I think you should still work at 
    // understanding the code before copy-pasting. But the basic premise 
    // is as follows: 
    public static String CreateFromEnumerable(IEnumerable enumerable) 
    { 
     // create (and store) a reference to your builder. This should 
     // be passed around instead of creating one-off instances within 
     // each method. 
     var sb = new StringBuilder(); 
     var i = 0; // counter 

     // Iterate over each object 
     IEnumerator enumerator = enumerable.GetEnumerator(); 
     while (enumerator.MoveNext()) 
     { 
      // Crab current object from enumerator 
      var obj = enumerator.Current; 

      // Cache the list of properties 
      var properties = obj.GetType().GetProperties(); 
      if (i++ == 0) 
      { 
       // if its the first item, use the properties list and 
       // output the heading column. 
       // Notice how the builder is passed as an argument. 
       AddHeading(sb, properties); 
      } 

      // every item will them be dumped as usual. 
      // Notice how the builder is passed as an argument. 
      AddData(sb, properties, obj); 
     } 

     // Return the final result as a string 
     return sb.ToString(); 
    } 

    // Build a heading from the properties of the object 
    private static void AddHeading(StringBuilder sb, PropertyInfo[] properties) 
    { 
     // quick short-circuit check 
     if (properties == null || properties.Length == 0) return; 

     // iterate over the properties 
     for (var p = 0; p < properties.Length; p++) 
     { 
      // if it's not the first property add a comma 
      if (p > 0) 
      { 
       sb.Append(","); 
      } 
      // add the property name, escaping as necessary 
      sb.Append(EscapeValue(properties[p].Name)); 
     } 

     // add a new line (this line is complete) 
     sb.AppendLine(); 
    } 

    // Build a line based on the properties and the object itself 
    private static void AddData(StringBuilder sb, PropertyInfo[] properties, Object obj) 
    { 
     // quick short-circuit check 
     if (properties == null || properties.Length == 0) return; 
     if (Object.ReferenceEquals(obj, null)) return; 

     // iterate over the properties 
     for (var p = 0; p < properties.Length; p++) 
     { 
      // if it's not the first property add a comma 
      if (p > 0) 
      { 
       sb.Append(","); 
      } 

      // Get the value of the property from the original object 
      // Also, convert it to a string so we can work with it. 
      var val = properties[p].GetValue(obj).ToString(); 

      // add the value, escaping as necessary 
      sb.Append(EscapeValue(val)); 
     } 

     // add a new line (this line is complete) 
     sb.AppendLine(); 
    } 

    // Escape the value when necessary (per CSV standards) 
    private static String EscapeValue(String value) 
    { 
     // quick short-circuit check 
     if (String.IsNullOrEmpty(value)) return String.Empty; 

     // If the value has a comma or a quote, we need to: 
     // 1. Wrap the value in quotations 
     // 2. Convert any existing quotations to double-quotations 
     if (value.IndexOf(',') > -1 || value.IndexOf('"') > -1) 
     { 
      return String.Concat("\"", value.Replace("\"", "\"\""), "\""); 
     } 

     // No modification needed--return as-is. 
     return value; 
    } 
}