모든 클래스 인스턴스에서 CSV를 만드는 방법을 찾고 있습니다.CSV (일반 속성) 일반 클래스
내가 원하는 것은 모든 클래스 (모든 인스턴스)를 CSV로 내보낼 수 있다는 것입니다.
some1은 가능한 해결책을 제시 할 수 있습니까? (이미 answered 경우).
thanx!
모든 클래스 인스턴스에서 CSV를 만드는 방법을 찾고 있습니다.CSV (일반 속성) 일반 클래스
내가 원하는 것은 모든 클래스 (모든 인스턴스)를 CSV로 내보낼 수 있다는 것입니다.
some1은 가능한 해결책을 제시 할 수 있습니까? (이미 answered 경우).
thanx!
사실, 비슷한 여기에 해결되었습니다
Best practices for serializing objects to a custom string format for use in an output file
당신에게이 유용한가요?
리플렉션을 사용하여 필드 이름과 값을 빼내어 문자열에 추가하는 샘플이 있습니다.
확장 메소드를 사용하지 않은 것 같습니다./ 정적 클래스를 만들었고 Hejndorf Per 메서드를 ost에 링크 된 메서드에 추가했습니다. 이제는 List <>에 메소드를 확장하는 방법을 모릅니다. 따라서 "User"클래스의 인스턴스를 포함하는 목록의 인스턴스에서 .ToCSV를 호출 할 수 있습니다. – no9
reflection을 사용하여 모든 클래스 속성/필드를 탐색하고이를 CSV에 쓸 수 있습니다. 더 나은 방법은 사용자 지정 특성을 정의하고 내보내려는 구성원을 꾸미고 해당 특성 만 내보내는 것입니다.
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; }
}
}
나는 두 개의 섹션으로 내 대답을 분리하고 : 를 첫 번째 인코딩, 헤더, 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"}}
그래서 .. 그냥 쓰기? 직렬화 프로세스이지만 XML 또는 Binary 대신 CSV를 사용합니다. 무슨 문제 있니? –
(a) 클래스에 대한 예제와 (b) 기대하는 CSV에 대한 예제를 제공하면 (a)에서 (b)로가는 방법에 대한 많은 답을 얻을 수 있습니다. –
실키 : 나는 그것을 쓸 수는 있지만 클래스에 속성을 추가 할 때 CSV에 대해 걱정할 필요가없는 일반용이 필요합니다. Doc : 사용자 (이름, 성, 나이 ...와 같은 간단한 데이터 클래스) . 나는 ";"과 같은 것을 생각하고 있었다. 스타터를위한 헤더를 포함하여 구분됩니다. 단순한 클래스의 경우 – no9