如何解决*读取*具有不同格式的多个部分的CSV文件的最佳做法
我是CsvHelper的一个非常满意的用户,它可以帮助我的软件接收一个非常大的文本文件,该文件有〜24个部分,每个部分的格式都不同。到目前为止,这是从业务线应用程序中将数据作为单个文件获取的最方便的方法(CsvHelper不参与创建文件,仅读取它)。
每行以该行的 type 为前缀,并带有按节标题和按节数据。我们使用制表符作为分隔符。
团队和员工组成的简单示例:
TEAM ID Name
TEAM 1 Engineering
TEAM 2 Janitorial
EE ID FName LName TeamId
EE 1 Bill Gates 1
EE 2 Larry Ellison 2
EE 3 Jeff Bezos 1
我使用TextReader
一次从文件中获取一行(格式不能包含多行字段),提取第一个标记并将行保存到MemoryStream
。当令牌更改时,它是一个新的部分,因此我以普通的方式将刚刚完成的内存流提供给CsvHelper,以生成我的C#对象。
这已经可靠地工作了一段时间了。
但是我是否错过了一些很酷的CsvHelper方法,可以通过一次简单的操作更直接地做到这一点?
编辑我不是要寻求替代的通用编码思路来解决此问题,这会引起很多意见。
我在问CsvHelper是否针对我错过的这个特定用例具有任何特定功能。我已经仔细研究了classmap的内容,却一无所获。
解决方法
以下是使用LINQPad的示例。
void Main()
{
var s = new StringBuilder();
s.AppendLine("TEAM ID Name");
s.AppendLine("TEAM 1 Engineering");
s.AppendLine("TEAM 2 Janitorial");
s.AppendLine("EE ID FName LName TeamId");
s.AppendLine("EE 1 Bill Gates 1");
s.AppendLine("EE 2 Larry Ellison 2");
s.AppendLine("EE 3 Jeff Bezos 1");
using (var reader = new StringReader(s.ToString()))
using (var csv = new CsvReader(reader,CultureInfo.InvariantCulture))
{
csv.Configuration.Delimiter = "\t";
var rowType = RowType.None;
var foos = new List<Foo>();
var bars = new List<Bar>();
while (csv.Read())
{
if (csv.GetField(1) == "ID")
{
csv.ReadHeader();
if (csv.GetField(0) == "TEAM")
{
rowType = RowType.Foo;
continue;
}
else if (csv.GetField(0) == "EE")
{
rowType = RowType.Bar;
continue;
}
else
{
rowType = RowType.None;
continue;
}
}
if (rowType == RowType.Foo)
{
foos.Add(csv.GetRecord<Foo>());
}
else if (rowType == RowType.Bar)
{
bars.Add(csv.GetRecord<Bar>());
}
}
foos.Dump();
bars.Dump();
}
}
public enum RowType
{
None = 0,Foo = 1,Bar = 2
}
public class Foo
{
[Name("ID")]
public int Id { get; set; }
public string Name { get; set; }
}
public class Bar
{
[Name("ID")]
public int Id { get; set; }
[Name("FName")]
public string FirstName { get; set; }
[Name("LName")]
public string LastName { get; set; }
public int TeamId { get; set; }
}
输出:
如果您有任何问题,请在评论中提出,并在此处进行进一步说明。
,这并非完全是“ CsvHelper方法”,但它可能与您要查找的内容很接近。
public class Program
{
static void Main(string[] args)
{
using (var stream = new MemoryStream())
using (var writer = new StreamWriter(stream))
using (var reader = new StreamReader(stream))
using (var csv = new CsvReader(reader,CultureInfo.InvariantCulture))
{
writer.WriteLine("TEAM\tId\tName");
writer.WriteLine("TEAM\t1\tEngineering");
writer.WriteLine("EE\tId\tFirstName\tLastName\tTeamId");
writer.WriteLine("EE\t1\tBill\tGates\t1");
writer.Flush();
stream.Position = 0;
csv.Configuration.Delimiter = "\t";
var teams = new List<Team>();
var employees = new List<Employee>();
var types = new Dictionary<string,ListType>
{
{ "TEAM",new ListType{ Type = typeof(Team),List = teams} },{ "EE",new ListType{ Type = typeof(Employee),List = employees} }
};
var lastType = string.Empty;
var currentType = string.Empty;
while (csv.Read())
{
currentType = csv.GetField<string>(0);
if (!types.ContainsKey(currentType))
throw new Exception($"{currentType} is not a valid type");
if (currentType == lastType)
{
types[currentType].List.Add(csv.GetRecord(types[currentType].Type));
}
else
{
csv.ReadHeader();
}
lastType = currentType;
}
}
}
}
public class ListType
{
public IList List { get; set; }
public Type Type { get; set; }
}
public class Team
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Employee
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int TeamId { get; set; }
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。