在 CsvHelper 中使用多种记录类型将记录分组在一起
Grouping records together using multiple record types in CsvHelper
我有一个很大的日志文件,其中包含我要解析的不同记录类型。它看起来像这样:
$L,8,PO
$L,8,SF
$P,8,P,0,102,0,19:08:34.463
$P,9,P,0,110,0,19:08:34.460
$P,8,P,0,105,0,19:08:34.407
$L,8,SF
$P,9,A,0,139,0,19:08:34.374
$P,15,P,0,103,0,19:08:34.532
$P,8,P,0,73,0,19:08:34.436
$L,8,SF
$L,8,PI
我目前正在使用 CsvHelper 并遵循 this example 如何使用 switch 语句读取多个记录类型。但是我有点卡住了,因为我想根据 $L 记录中包含的值对 $P 记录进行分组,然后将输出写入单独的 CSV 文件。
例如,第一个和最后一个 $L 记录都在第二个字段中包含一个 8,加上 PO/PI 消息(这将是我的文件的 start/end 所有 $P 记录包含8 在第二个字段中)。 8.csv 的文件输出如下所示:
$P,8,P,0,102,0,19:08:34.463
$P,8,P,0,105,0,19:08:34.407
$P,8,P,0,73,0,19:08:34.436
除了以这种方式将它们组合在一起之外,我还想根据包含 SF 和数字 8 的 $L 消息在 $P 记录之前添加一个数字。上面有 3 条 SF 消息包含 SF 和8,所以最终文件看起来像这样:
1,$P,8,P,0,102,0,19:08:34.463
1,$P,8,P,0,105,0,19:08:34.407
2,$P,8,P,0,73,0,19:08:34.436
完成此任务的最佳方法是什么?目前,我正在将所有包含相同 ID 号的 $P 消息添加到键值对为:List<$P Record> 的字典中,我不太确定如何根据这些值对 $P 记录进行分组另一条记录。
尝试这样的事情。向记录添加行然后对记录进行分组更容易。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace ConsoleApplication184
{
class Program
{
const string FILENAME = @"c:\temp\test.txt";
static void Main(string[] args)
{
int count = 0;
string line = "";
StreamReader reader = new StreamReader(FILENAME);
List<Record> records = new List<Record>();
while ((line = reader.ReadLine()) != null)
{
int startComment = line.IndexOf("//");
if (startComment >= 0)
{
line = line.Substring(0, startComment);
}
line = line.Trim();
string[] splitArray = line.Split(new char[] { ',' }).ToArray();
Record newRecord = new Record();
newRecord.car = int.Parse(splitArray[1]);
newRecord.type = (Record.RECORD_TYPE)Enum.Parse(typeof(Record.RECORD_TYPE), splitArray[2]);
records.Add(newRecord);
switch (splitArray[0])
{
case "$P":
newRecord.message = line;
break;
}
}
var cars = records.GroupBy(x => x.car);
foreach (var car in cars)
{
int lap = 0;
int stint = 0;
foreach (Record record in car)
{
record.lap = lap;
record.stint = stint;
switch (record.type)
{
case Record.RECORD_TYPE.SF:
record.lap = ++lap;
break;
case Record.RECORD_TYPE.P:
string output = string.Join(",", new string[] { record.stint.ToString(), record.lap.ToString(), record.message });
Console.WriteLine(output);
break;
case Record.RECORD_TYPE.PO :
record.stint = ++stint;
break;
}
}
}
Console.ReadLine();
}
}
public class Record
{
public enum RECORD_TYPE
{
PO,
SF,
P,
PI,
A
}
public RECORD_TYPE type { get; set; }
public int stint { get; set; }
public int lap { get; set; }
public int car { get; set; }
public string message { get; set; }
}
}
我有一个很大的日志文件,其中包含我要解析的不同记录类型。它看起来像这样:
$L,8,PO
$L,8,SF
$P,8,P,0,102,0,19:08:34.463
$P,9,P,0,110,0,19:08:34.460
$P,8,P,0,105,0,19:08:34.407
$L,8,SF
$P,9,A,0,139,0,19:08:34.374
$P,15,P,0,103,0,19:08:34.532
$P,8,P,0,73,0,19:08:34.436
$L,8,SF
$L,8,PI
我目前正在使用 CsvHelper 并遵循 this example 如何使用 switch 语句读取多个记录类型。但是我有点卡住了,因为我想根据 $L 记录中包含的值对 $P 记录进行分组,然后将输出写入单独的 CSV 文件。
例如,第一个和最后一个 $L 记录都在第二个字段中包含一个 8,加上 PO/PI 消息(这将是我的文件的 start/end 所有 $P 记录包含8 在第二个字段中)。 8.csv 的文件输出如下所示:
$P,8,P,0,102,0,19:08:34.463
$P,8,P,0,105,0,19:08:34.407
$P,8,P,0,73,0,19:08:34.436
除了以这种方式将它们组合在一起之外,我还想根据包含 SF 和数字 8 的 $L 消息在 $P 记录之前添加一个数字。上面有 3 条 SF 消息包含 SF 和8,所以最终文件看起来像这样:
1,$P,8,P,0,102,0,19:08:34.463
1,$P,8,P,0,105,0,19:08:34.407
2,$P,8,P,0,73,0,19:08:34.436
完成此任务的最佳方法是什么?目前,我正在将所有包含相同 ID 号的 $P 消息添加到键值对为:List<$P Record> 的字典中,我不太确定如何根据这些值对 $P 记录进行分组另一条记录。
尝试这样的事情。向记录添加行然后对记录进行分组更容易。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace ConsoleApplication184
{
class Program
{
const string FILENAME = @"c:\temp\test.txt";
static void Main(string[] args)
{
int count = 0;
string line = "";
StreamReader reader = new StreamReader(FILENAME);
List<Record> records = new List<Record>();
while ((line = reader.ReadLine()) != null)
{
int startComment = line.IndexOf("//");
if (startComment >= 0)
{
line = line.Substring(0, startComment);
}
line = line.Trim();
string[] splitArray = line.Split(new char[] { ',' }).ToArray();
Record newRecord = new Record();
newRecord.car = int.Parse(splitArray[1]);
newRecord.type = (Record.RECORD_TYPE)Enum.Parse(typeof(Record.RECORD_TYPE), splitArray[2]);
records.Add(newRecord);
switch (splitArray[0])
{
case "$P":
newRecord.message = line;
break;
}
}
var cars = records.GroupBy(x => x.car);
foreach (var car in cars)
{
int lap = 0;
int stint = 0;
foreach (Record record in car)
{
record.lap = lap;
record.stint = stint;
switch (record.type)
{
case Record.RECORD_TYPE.SF:
record.lap = ++lap;
break;
case Record.RECORD_TYPE.P:
string output = string.Join(",", new string[] { record.stint.ToString(), record.lap.ToString(), record.message });
Console.WriteLine(output);
break;
case Record.RECORD_TYPE.PO :
record.stint = ++stint;
break;
}
}
}
Console.ReadLine();
}
}
public class Record
{
public enum RECORD_TYPE
{
PO,
SF,
P,
PI,
A
}
public RECORD_TYPE type { get; set; }
public int stint { get; set; }
public int lap { get; set; }
public int car { get; set; }
public string message { get; set; }
}
}