Saya memiliki daftar nilai integer (List) dan ingin menghasilkan string nilai yang dipisahkan koma. Itu semua item dalam daftar keluaran ke daftar dipisahkan koma tunggal.
Pikiranku ... 1. meneruskan daftar ke metode. 2. Gunakan stringbuilder untuk mengulang daftar dan menambahkan koma 3. Uji karakter terakhir dan jika itu adalah koma, hapus.
Apa yang kamu pikirkan Apakah ini cara terbaik?
Bagaimana kode saya berubah jika saya ingin menangani tidak hanya integer (paket saya saat ini) tetapi juga string, long, doubles, bools, dll, dll. Di masa mendatang? Saya kira membuatnya menerima daftar jenis apa pun.
List<int>
tidak memiliki metodeSelect
dalam kerangka 3.5 kecuali saya kehilangan sesuatu.using
pernyataan.System.Linq.Enumerable
(dan tentu saja Anda perluSystem.Core.dll
perakitan, tetapi mungkin Anda sudah memilikinya). Anda lihat,List<int>
tidak pernah memilikiSelect
metode. Sebaliknya,System.Linq.Enumerable
mendefinisikanSelect
sebagai metode ekstensiIEnumerable<T>
, yangList<int>
merupakan contoh dari. Jadi, Anda perluSystem.Linq.Enumerable
mengimpor untuk memilih metode ekstensi ini.di 3,5, saya masih bisa melakukan ini. Ini jauh lebih sederhana dan tidak membutuhkan lambda.
String.Join(",", myList.ToArray<string>());
sumber
ToArray()
MetodeList<int>
tidak dapat digunakan dengan argumen tipe dalam kerangka 3.5 kecuali saya kehilangan sesuatu.Anda dapat membuat metode ekstensi yang dapat Anda panggil di IEnumerable mana pun:
public static string JoinStrings<T>( this IEnumerable<T> values, string separator) { var stringValues = values.Select(item => (item == null ? string.Empty : item.ToString())); return string.Join(separator, stringValues.ToArray()); }
Kemudian Anda bisa memanggil metode di daftar asli:
string commaSeparated = myList.JoinStrings(", ");
sumber
Anda bisa menggunakan
String.Join
.String.Join( ",", Array.ConvertAll( list.ToArray(), element => element.ToString() ) );
sumber
ConvertAll
sini - keduanyaint
danstring
akan disimpulkan.Array.ConvertAll(...' you can just do
list.ConvertAll (e => e.ToString ()). ToArray) `, cukup sedikit mengetik.Jika ada badan yang ingin mengonversi daftar objek kelas khusus, bukan daftar string, maka ganti metode ToString kelas Anda dengan representasi baris csv kelas Anda.
Public Class MyClass{ public int Id{get;set;} public String PropertyA{get;set;} public override string ToString() { return this.Id+ "," + this.PropertyA; } }
Kemudian kode berikut dapat digunakan untuk mengubah daftar kelas ini menjadi CSV dengan kolom header
string csvHeaderRow = String.Join(",", typeof(MyClass).GetProperties(BindingFlags.Public | BindingFlags.Instance).Select(x => x.Name).ToArray<string>()) + Environment.NewLine; string csv= csvHeaderRow + String.Join(Environment.NewLine, MyClass.Select(x => x.ToString()).ToArray());
sumber
Saya menjelaskannya secara mendalam di posting ini . Saya hanya akan menempelkan kode di sini dengan deskripsi singkat.
Inilah metode yang membuat baris tajuk. Ini menggunakan nama properti sebagai nama kolom.
private static void CreateHeader<T>(List<T> list, StreamWriter sw) { PropertyInfo[] properties = typeof(T).GetProperties(); for (int i = 0; i < properties.Length - 1; i++) { sw.Write(properties[i].Name + ","); } var lastProp = properties[properties.Length - 1].Name; sw.Write(lastProp + sw.NewLine); }
Metode ini membuat semua baris nilai
private static void CreateRows<T>(List<T> list, StreamWriter sw) { foreach (var item in list) { PropertyInfo[] properties = typeof(T).GetProperties(); for (int i = 0; i < properties.Length - 1; i++) { var prop = properties[i]; sw.Write(prop.GetValue(item) + ","); } var lastProp = properties[properties.Length - 1]; sw.Write(lastProp.GetValue(item) + sw.NewLine); } }
Dan inilah metode yang menyatukan mereka dan membuat file yang sebenarnya.
public static void CreateCSV<T>(List<T> list, string filePath) { using (StreamWriter sw = new StreamWriter(filePath)) { CreateHeader(list, sw); CreateRows(list, sw); } }
sumber
|
file yang dipisahkan menggunakan versi yang ditingkatkan. Terima kasih!Karena kode dalam tautan yang diberikan oleh @Frank Buat File CSV dari Daftar Generik .NET, ada sedikit masalah untuk mengakhiri setiap baris dengan
,
saya memodifikasi kode untuk menghilangkannya. Semoga ini membantu seseorang./// <summary> /// Creates the CSV from a generic list. /// </summary>; /// <typeparam name="T"></typeparam>; /// <param name="list">The list.</param>; /// <param name="csvNameWithExt">Name of CSV (w/ path) w/ file ext.</param>; public static void CreateCSVFromGenericList<T>(List<T> list, string csvCompletePath) { if (list == null || list.Count == 0) return; //get type from 0th member Type t = list[0].GetType(); string newLine = Environment.NewLine; if (!Directory.Exists(Path.GetDirectoryName(csvCompletePath))) Directory.CreateDirectory(Path.GetDirectoryName(csvCompletePath)); if (!File.Exists(csvCompletePath)) File.Create(csvCompletePath); using (var sw = new StreamWriter(csvCompletePath)) { //make a new instance of the class name we figured out to get its props object o = Activator.CreateInstance(t); //gets all properties PropertyInfo[] props = o.GetType().GetProperties(); //foreach of the properties in class above, write out properties //this is the header row sw.Write(string.Join(",", props.Select(d => d.Name).ToArray()) + newLine); //this acts as datarow foreach (T item in list) { //this acts as datacolumn var row = string.Join(",", props.Select(d => item.GetType() .GetProperty(d.Name) .GetValue(item, null) .ToString()) .ToArray()); sw.Write(row + newLine); } } }
sumber
dev
ada, tetapi bukan filenya ... apakah saya tidak menggunakannya, bukan?sw.Write(string.Join(",", props.Select(d => d.Name).ToArray()) + newLine);
Tidak diuji tetapi tidak tahu apa yang ingin Anda capaiSaya suka metode ekstensi sederhana yang bagus
public static string ToCsv(this List<string> itemList) { return string.Join(",", itemList); }
Kemudian Anda bisa memanggil metode di daftar asli:
string CsvString = myList.ToCsv();
Lebih bersih dan lebih mudah dibaca daripada beberapa saran lainnya.
sumber
Solusi apa pun hanya berfungsi jika Cantumkan daftar (string)
Jika Anda memiliki daftar umum Objek Anda sendiri seperti daftar (mobil) di mana mobil memiliki properti n, Anda harus mengulang PropertiesInfo dari setiap objek mobil.
Lihat: http://www.csharptocsharp.com/generate-csv-from-generic-list
sumber
Library CsvHelper Sangat Populer Di Nuget. Layak Banget! https://github.com/JoshClose/CsvHelper/wiki/Basics
Menggunakan CsvHelper sangat mudah. Pengaturan defaultnya disiapkan untuk skenario yang paling umum.
Berikut ini sedikit data penyiapan.
Actors.csv:
Id,FirstName,LastName 1,Arnold,Schwarzenegger 2,Matt,Damon 3,Christian,Bale
Actor.cs (objek kelas khusus yang mewakili aktor):
public class Actor { public int Id { get; set; } public string FirstName { get; set; } public string LastName { get; set; } }
Membaca file CSV menggunakan CsvReader:
var csv = new CsvReader( new StreamReader( "Actors.csv" ) );
var actorList = csv.GetRecords ();
Menulis ke file CSV.
using (var csv = new CsvWriter( new StreamWriter( "Actors.csv" ) )) { csv.WriteRecords( actorsList ); }
sumber
Masalah dengan String.Join adalah Anda tidak menangani kasus koma yang sudah ada di nilainya. Jika ada koma, Anda mengapit nilai di Quotes dan mengganti semua Quotes yang ada dengan Quotes ganda.
String.Join(",",{"this value has a , in it","This one doesn't", "This one , does"});
Lihat Modul CSV
sumber
Untuk alasan apa pun, @AliUmair mengembalikan hasil edit ke jawabannya yang memperbaiki kodenya yang tidak berjalan sebagaimana mestinya, jadi berikut adalah versi yang berfungsi yang tidak memiliki kesalahan akses file dan menangani nilai properti objek null dengan benar:
/// <summary> /// Creates the CSV from a generic list. /// </summary>; /// <typeparam name="T"></typeparam>; /// <param name="list">The list.</param>; /// <param name="csvNameWithExt">Name of CSV (w/ path) w/ file ext.</param>; public static void CreateCSVFromGenericList<T>(List<T> list, string csvCompletePath) { if (list == null || list.Count == 0) return; //get type from 0th member Type t = list[0].GetType(); string newLine = Environment.NewLine; if (!Directory.Exists(Path.GetDirectoryName(csvCompletePath))) Directory.CreateDirectory(Path.GetDirectoryName(csvCompletePath)); using (var sw = new StreamWriter(csvCompletePath)) { //make a new instance of the class name we figured out to get its props object o = Activator.CreateInstance(t); //gets all properties PropertyInfo[] props = o.GetType().GetProperties(); //foreach of the properties in class above, write out properties //this is the header row sw.Write(string.Join(",", props.Select(d => d.Name).ToArray()) + newLine); //this acts as datarow foreach (T item in list) { //this acts as datacolumn var row = string.Join(",", props.Select(d => $"\"{item.GetType().GetProperty(d.Name).GetValue(item, null)?.ToString()}\"") .ToArray()); sw.Write(row + newLine); } } }
sumber
http://cc.davelozinski.com/c-sharp/the-fastest-way-to-read-and-process-text-files
Situs web ini melakukan beberapa pengujian ekstensif tentang cara menulis ke file menggunakan penulis buffered, membaca baris demi baris tampaknya adalah cara terbaik, menggunakan pembuat string adalah salah satu yang paling lambat.
Saya banyak menggunakan tekniknya untuk menulis sesuatu agar file itu bekerja dengan baik.
sumber
Metode ekstensi ToCsv () tujuan umum:
Contoh Penggunaan:
"123".ToCsv() // "1,2,3" "123".ToCsv(", ") // "1, 2, 3" new List<int> { 1, 2, 3 }.ToCsv() // "1,2,3" new List<Tuple<int, string>> { Tuple.Create(1, "One"), Tuple.Create(2, "Two") } .ToCsv(t => t.Item2); // "One,Two" ((string)null).ToCsv() // throws exception ((string)null).ToCsvOpt() // "" ((string)null).ToCsvOpt(ReturnNullCsv.WhenNull) // null
Penerapan
/// <summary> /// Specifies when ToCsv() should return null. Refer to ToCsv() for IEnumerable[T] /// </summary> public enum ReturnNullCsv { /// <summary> /// Return String.Empty when the input list is null or empty. /// </summary> Never, /// <summary> /// Return null only if input list is null. Return String.Empty if list is empty. /// </summary> WhenNull, /// <summary> /// Return null when the input list is null or empty /// </summary> WhenNullOrEmpty, /// <summary> /// Throw if the argument is null /// </summary> ThrowIfNull } /// <summary> /// Converts IEnumerable list of values to a comma separated string values. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="values">The values.</param> /// <param name="joinSeparator"></param> /// <returns>System.String.</returns> public static string ToCsv<T>( this IEnumerable<T> values, string joinSeparator = ",") { return ToCsvOpt<T>(values, null /*selector*/, ReturnNullCsv.ThrowIfNull, joinSeparator); } /// <summary> /// Converts IEnumerable list of values to a comma separated string values. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="values">The values.</param> /// <param name="selector">An optional selector</param> /// <param name="joinSeparator"></param> /// <returns>System.String.</returns> public static string ToCsv<T>( this IEnumerable<T> values, Func<T, string> selector, string joinSeparator = ",") { return ToCsvOpt<T>(values, selector, ReturnNullCsv.ThrowIfNull, joinSeparator); } /// <summary> /// Converts IEnumerable list of values to a comma separated string values. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="values">The values.</param> /// <param name="returnNullCsv">Return mode (refer to enum ReturnNullCsv).</param> /// <param name="joinSeparator"></param> /// <returns>System.String.</returns> public static string ToCsvOpt<T>( this IEnumerable<T> values, ReturnNullCsv returnNullCsv = ReturnNullCsv.Never, string joinSeparator = ",") { return ToCsvOpt<T>(values, null /*selector*/, returnNullCsv, joinSeparator); } /// <summary> /// Converts IEnumerable list of values to a comma separated string values. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="values">The values.</param> /// <param name="selector">An optional selector</param> /// <param name="returnNullCsv">Return mode (refer to enum ReturnNullCsv).</param> /// <param name="joinSeparator"></param> /// <returns>System.String.</returns> public static string ToCsvOpt<T>( this IEnumerable<T> values, Func<T, string> selector, ReturnNullCsv returnNullCsv = ReturnNullCsv.Never, string joinSeparator = ",") { switch (returnNullCsv) { case ReturnNullCsv.Never: if (!values.AnyOpt()) return string.Empty; break; case ReturnNullCsv.WhenNull: if (values == null) return null; break; case ReturnNullCsv.WhenNullOrEmpty: if (!values.AnyOpt()) return null; break; case ReturnNullCsv.ThrowIfNull: if (values == null) throw new ArgumentOutOfRangeException("ToCsvOpt was passed a null value with ReturnNullCsv = ThrowIfNull."); break; default: throw new ArgumentOutOfRangeException("returnNullCsv", returnNullCsv, "Out of range."); } if (selector == null) { if (typeof(T) == typeof(Int16) || typeof(T) == typeof(Int32) || typeof(T) == typeof(Int64)) { selector = (v) => Convert.ToInt64(v).ToStringInvariant(); } else if (typeof(T) == typeof(decimal)) { selector = (v) => Convert.ToDecimal(v).ToStringInvariant(); } else if (typeof(T) == typeof(float) || typeof(T) == typeof(double)) { selector = (v) => Convert.ToDouble(v).ToString(CultureInfo.InvariantCulture); } else { selector = (v) => v.ToString(); } } return String.Join(joinSeparator, values.Select(v => selector(v))); } public static string ToStringInvariantOpt(this Decimal? d) { return d.HasValue ? d.Value.ToStringInvariant() : null; } public static string ToStringInvariant(this Decimal d) { return d.ToString(CultureInfo.InvariantCulture); } public static string ToStringInvariantOpt(this Int64? l) { return l.HasValue ? l.Value.ToStringInvariant() : null; } public static string ToStringInvariant(this Int64 l) { return l.ToString(CultureInfo.InvariantCulture); } public static string ToStringInvariantOpt(this Int32? i) { return i.HasValue ? i.Value.ToStringInvariant() : null; } public static string ToStringInvariant(this Int32 i) { return i.ToString(CultureInfo.InvariantCulture); } public static string ToStringInvariantOpt(this Int16? i) { return i.HasValue ? i.Value.ToStringInvariant() : null; } public static string ToStringInvariant(this Int16 i) { return i.ToString(CultureInfo.InvariantCulture); }
sumber
Ini adalah metode ekstensi saya, ia mengembalikan string untuk kesederhanaan tetapi implementasi saya menulis file ke danau data.
Ini menyediakan pembatas apa pun, menambahkan tanda kutip ke string (jika mengandung pemisah) dan penawaran akan kosong dan kosong.
/// <summary> /// A class to hold extension methods for C# Lists /// </summary> public static class ListExtensions { /// <summary> /// Convert a list of Type T to a CSV /// </summary> /// <typeparam name="T">The type of the object held in the list</typeparam> /// <param name="items">The list of items to process</param> /// <param name="delimiter">Specify the delimiter, default is ,</param> /// <returns></returns> public static string ToCsv<T>(this List<T> items, string delimiter = ",") { Type itemType = typeof(T); var props = itemType.GetProperties(BindingFlags.Public | BindingFlags.Instance).OrderBy(p => p.Name); var csv = new StringBuilder(); // Write Headers csv.AppendLine(string.Join(delimiter, props.Select(p => p.Name))); // Write Rows foreach (var item in items) { // Write Fields csv.AppendLine(string.Join(delimiter, props.Select(p => GetCsvFieldasedOnValue(p, item)))); } return csv.ToString(); } /// <summary> /// Provide generic and specific handling of fields /// </summary> /// <typeparam name="T"></typeparam> /// <param name="p"></param> /// <param name="item"></param> /// <returns></returns> private static object GetCsvFieldasedOnValue<T>(PropertyInfo p, T item) { string value = ""; try { value = p.GetValue(item, null)?.ToString(); if (value == null) return "NULL"; // Deal with nulls if (value.Trim().Length == 0) return ""; // Deal with spaces and blanks // Guard strings with "s, they may contain the delimiter! if (p.PropertyType == typeof(string)) { value = string.Format("\"{0}\"", value); } } catch (Exception ex) { throw ex; } return value; } }
Pemakaian:
// Tab Delimited (TSV) var csv = MyList.ToCsv<MyClass>("\t");
sumber