*读取*具有不同格式的多个部分的CSV文件的最佳做法

如何解决*读取*具有不同格式的多个部分的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; }
}

输出:

enter image description here

如果您有任何问题,请在评论中提出,并在此处进行进一步说明。

,

这并非完全是“ 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 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?