这是 Per Hejndorf 的 CSV 想法的简化版本(没有内存开销,因为它依次产生每一行)。由于受欢迎的需求,它还通过使用Concat
.
2017 年 5 月 18 日更新
这个例子从来没有打算成为一个完整的解决方案,只是推进了 Per Hejndorf 发布的原始想法。要生成有效的 CSV,您需要将文本中的任何文本分隔符替换为 2 个分隔符的序列。例如一个简单的.Replace("\"", "\"\"")
.
2016 年 2 月 12 日更新
今天在一个项目中再次使用我自己的代码后,我意识到当我从@Per Hejndorf
. 假设默认分隔符为“,”(逗号)并将分隔符作为第二个可选参数更有意义。我自己的库版本还提供了第三个header
参数,用于控制是否应返回标题行,因为有时您只需要数据。
例如
public static IEnumerable<string> ToCsv<T>(IEnumerable<T> objectlist, string separator = ",", bool header = true)
{
FieldInfo[] fields = typeof(T).GetFields();
PropertyInfo[] properties = typeof(T).GetProperties();
if (header)
{
yield return String.Join(separator, fields.Select(f => f.Name).Concat(properties.Select(p=>p.Name)).ToArray());
}
foreach (var o in objectlist)
{
yield return string.Join(separator, fields.Select(f=>(f.GetValue(o) ?? "").ToString())
.Concat(properties.Select(p=>(p.GetValue(o,null) ?? "").ToString())).ToArray());
}
}
所以你然后像这样将它用于逗号分隔:
foreach (var line in ToCsv(objects))
{
Console.WriteLine(line);
}
或者像这样用于另一个分隔符(例如 TAB):
foreach (var line in ToCsv(objects, "\t"))
{
Console.WriteLine(line);
}
实际例子
将列表写入逗号分隔的 CSV 文件
using (TextWriter tw = File.CreateText("C:\testoutput.csv"))
{
foreach (var line in ToCsv(objects))
{
tw.WriteLine(line);
}
}
或者用制表符分隔
using (TextWriter tw = File.CreateText("C:\testoutput.txt"))
{
foreach (var line in ToCsv(objects, "\t"))
{
tw.WriteLine(line);
}
}
如果您有复杂的字段/属性,则需要将它们从选择子句中过滤掉。
以前的版本和详细信息如下:
这是 Per Hejndorf 的 CSV 想法的简化版本(没有内存开销,因为它依次产生每一行)并且只有 4 行代码:)
public static IEnumerable<string> ToCsv<T>(string separator, IEnumerable<T> objectlist)
{
FieldInfo[] fields = typeof(T).GetFields();
yield return String.Join(separator, fields.Select(f => f.Name).ToArray());
foreach (var o in objectlist)
{
yield return string.Join(separator, fields.Select(f=>(f.GetValue(o) ?? "").ToString()).ToArray());
}
}
你可以像这样迭代它:
foreach (var line in ToCsv(",", objects))
{
Console.WriteLine(line);
}
whereobjects
是一个强类型的对象列表。
此变体包括公共字段和简单的公共属性:
public static IEnumerable<string> ToCsv<T>(string separator, IEnumerable<T> objectlist)
{
FieldInfo[] fields = typeof(T).GetFields();
PropertyInfo[] properties = typeof(T).GetProperties();
yield return String.Join(separator, fields.Select(f => f.Name).Concat(properties.Select(p=>p.Name)).ToArray());
foreach (var o in objectlist)
{
yield return string.Join(separator, fields.Select(f=>(f.GetValue(o) ?? "").ToString())
.Concat(properties.Select(p=>(p.GetValue(o,null) ?? "").ToString())).ToArray());
}
}