2011-06-01 31 views
9

sonucu IEnumerable<T>Bir CSV dosyasına IEnumerable <T>

türünde LINQ sorgusu sonucu alıyorum LINQ

sonucundan oluşturulacak bir CSV dosyası istiyorum Aşağıdaki sorgudan sonuç alıyorum

var r = from table in myDataTable.AsEnumerable() 
     orderby table.Field<string>(para1) 
     group table by new { Name = table[para1], Y = table[para2] } 
     into ResultTable 
     select new 
     { 
      Name = ResultTable.Key, 
      Count = ResultTable.Count() 
     }; 
+0

T türü nedir? –

+0

Bu soru biraz açık değil, "gerçek bir soru" olarak kapatmak için 2 oy zaten var. Lütfen http://tinyurl.com/so-hints adresine bakın ve soruyu geliştirip geliştiremeyeceğinizi görün. –

cevap

13

Kontrol bu

public static class LinqToCSV 
    { 
     public static string ToCsv<T>(this IEnumerable<T> items) 
      where T : class 
     { 
      var csvBuilder = new StringBuilder(); 
      var properties = typeof(T).GetProperties(); 
      foreach (T item in items) 
      { 
       string line = string.Join(",",properties.Select(p => p.GetValue(item, null).ToCsvValue()).ToArray()); 
       csvBuilder.AppendLine(line); 
      } 
      return csvBuilder.ToString(); 
     } 

     private static string ToCsvValue<T>(this T item) 
     { 
      if(item == null) return "\"\""; 

      if (item is string) 
      { 
       return string.Format("\"{0}\"", item.ToString().Replace("\"", "\\\"")); 
      } 
      double dummy; 
      if (double.TryParse(item.ToString(), out dummy)) 
      { 
       return string.Format("{0}", item); 
      } 
      return string.Format("\"{0}\"", item); 
     } 
    } 

Tam kodu: Scott Hanselman's ComputerZen Blog - From Linq To CSV

+0

Çözüm için teşekkürler – usr021986

+0

@ScottHanselman Bu kodda bir hata var. */"' Kullanarak dizelerden alıntılar çıkarmaya çalışır. Bu doğru değil. CSV'ler için çift tırnak işaretleri kullanılarak tırnak işaretleri kaçtı. Https://en.wikipedia.org/wiki/Comma-separated_values ​​ – MgSam

5
IEnumerable<string> lines = r.Select(x => String.Format("{0},{1}", r.Name, r.Count)); 
System.IO.File.WriteAllLines(path, lines); 

üretecek:

name1,count1 
name2,count2 
... 
+0

Amacınızı anlamıyorum. IEnumrable usr021986

+0

@abatishchev sonucundan csv dosyasını oluşturmak istiyorum: Bu işe yaramaz: IEnumerable 'IEnumerable ' için dönüştürülemiyor. –

+0

@Daniel: Tabii ki, bir yazım hatasıydı, yani IEnumerable ', ama eğer OP IE IE'ye karşı istiyorsa, onun sorusu mantıklı değil. – abatishchev

0

Sorunun ne olduğunu farketmeden yaptığınız bir Genel yöntemini kullanmak istediğinizi varsayalım?

şey

public void ToCSV<T>(IEnumerable<T>, TextWriter writer) . . . 

üstesinden olamaz sorun

gibi T sen T dahili özelliklerine, ya da T ihtiyaçları hakkında bilmeniz gereken T her bir öğesini ayırmak virgül, karmaşık bir tür olmasıdır Kendini bir CSV dizisi olarak nasıl yazacağını biliyorsunuz, bu da bir ICSVRow ara yüzüne ihtiyacınız olacak ve T'yi ICSVRow uygulayan nesnelerle sınırlamanız gerektiği anlamına geliyor. Bu da anonim türler için işe yaramayacağı anlamına gelir.

Herhangi bir sorunuz sadece cevap verin.

+0

Evet, genel metodu T – usr021986

+0

@ user373083'ten bağımsız olarak istiyorum: O zaman sayılan türün özelliklerine ulaşmak için yansıma kullanmanız gerekecek, bu bir solucan konservesi olabilir, ya çok olması gerekecek ToCSV'nin T ile ne yapacağına dair kesin ya da bir kabusa dönüşecek. Refelection ile iyi misiniz, yoksa start_ kodunu almak için biraz yayınlamalı mıyım? –

2

onun size gerçekten ne istediğini net, ama bu bir çözüm public void Read() {

var r = from table in myDataTable.AsEnumerable() 
      orderby table.Field<string>(para1) 
      group table by new { Name = table[para1], Y = table[para2] } 
       into ResultTable 
       select new NameCount() 
       { 
        Name = ResultTable.Key, 
        Count = ResultTable.Count() 
       }.ToString(); 

    //Write all r to a File 
} 
public class NameCount 
{ 
    public string Name { get; set; } 
    public int Count { get; set; } 
    public string ToString() 
    { 
     return string.Format("{0},{1}\r\n", Name, Count); 
    } 
} 
1
olabilir değil

Bu, herhangi bir IEnumerable için kullanıyorum temel bir çözümdür:

using System.Reflection; 
using System.Text; 
//***   
    public void ToCSV<T>(IEnumerable<T> items, string filePath) 
    { 
     var dataTable = new DataTable(typeof(T).Name); 
     PropertyInfo[] props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance); 
     foreach (var prop in props) 
      dataTable.Columns.Add(prop.Name, prop.PropertyType); 

     foreach (var item in items) 
     { 
      var values = new object[props.Length]; 
      for (var i = 0; i < props.Length; i++) 
      { 
       values[i] = props[i].GetValue(item, null); 
      } 
      dataTable.Rows.Add(values); 
     } 

     StringBuilder fileContent = new StringBuilder(); 
     foreach (var col in dataTable.Columns) 
      fileContent.Append(col.ToString() + ","); 

     fileContent.Replace(",", System.Environment.NewLine, fileContent.Length - 1, 1); 

     foreach (DataRow dr in dataTable.Rows) 
     { 
      foreach (var column in dr.ItemArray) 
       fileContent.Append("\"" + column.ToString() + "\","); 

      fileContent.Replace(",", System.Environment.NewLine, fileContent.Length - 1, 1); 
     } 

     //good place to validate File.Exist or catch exceptions 
     System.IO.File.WriteAllText(filePath, fileContent.ToString());    
    } 
+0

Eğer istisnayı ele almaya gerek yok, ilk etapta onu yakalamak için bir nokta yok. İstisnalar tutulabilecekleri yerde tutulmalı – mason

+0

Doğru, kullandığım kodun bir kısmını kaldırıyorum ve bu bölümü de kaldırmayı unutuyorum. –

İlgili konular