c# - 在 C# 中解析复杂的多行 CSV 文件
问题描述
我已经搜索了该站点,并找到了多个有关如何使用多种方法完成 C# 解析的示例……但在这种特定情况下没有找到可以帮助我的示例。我有一个需要解析的复杂 CSV 文件。这是一些标头数据的示例...
REPORT TITLE,New Query,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
REPORT DESCRIPTION,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
GENERATED,12/20/2019 7:33 AM ET,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
Client Name,Client A,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
Time Frame,Last Completed Period,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,Calendar year,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
Received Date,Custom,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,01/01/2015 - 12/31/2015,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
Service Date,Custom,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,01/01/2015 - 12/31/2015,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
Adjustments,CHOICE(S),,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,Phone Calibration,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
View,N/A,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
SERVICE LINE,Service Line Example A,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
SITE,General 1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,General 2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,General 3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,General 4,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,General 5,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,General 7,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
FILTER,CHOICE(S),,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
Client ID,'00001',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,'00002',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,'00003',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,'00004',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,'00005',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,'00006',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
对于 CSV 文件的格式,我无能为力,因为它是遗留系统的一部分。放置在每行末尾的 40 个逗号以及用作行分隔符的逗号由系统放置。
到目前为止,这是我的代码所在的位置...
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.VisualBasic.FileIO;
using System.Text.RegularExpressions;
namespace ConsoleUI
{
class Program
{
static void Main(string[] args)
{
var sourcePath = @"L:\sourceData.csv";
var delimiter = ",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,";
var tempPath = Path.GetTempFileName();
var lineNumber = 0;
var splitExpression = new Regex(@"(" + delimiter + @")(,)(?=(?:[^""]|""[^""]*"")*$)");
using (var writer = new StreamWriter(tempPath))
using (var reader = new StreamReader(sourcePath))
{
string line = null;
while ((line = reader.ReadLine()) != null)
{
lineNumber++;
var rows = splitExpression.Split(line).Where(s => s != delimiter).ToArray();
// This is where I need to place the parsed data into objects
writer.WriteLine(string.Join(delimiter, rows));
}
}
}
}
}
最终,我需要将每个已解析的数据移动到它自己定义的对象中。我已经建立了那个类。
在这一点上,任何可以提供的帮助都将被视为节日奇迹!谢谢你的时间。
解决方案
尝试以下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = @"c:\temp\test.csv";
static void Main(string[] args)
{
StreamReader reader = new StreamReader(FILENAME);
string line = "";
Report report = new Report();
string header = "";
while ((line = reader.ReadLine()) != null)
{
List<string> data = new List<string>();
string[] row = line.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToArray();
if (row.Length > 0)
{
if (line.StartsWith(","))
{
data = row.ToList();
}
else
{
header = row[0];
data = row.Skip(1).ToList();
}
if (data.Count == 0) continue;
switch (header)
{
case "REPORT TITLE":
report.title = data[0];
break;
case "REPORT DESCRIPTION":
report.description = data[0];
break;
case "GENERATED":
report.generated = data[0];
break;
case "Client Name":
report.name = data[0];
break;
case "Time Frame":
if (report.timeFrame == null) report.timeFrame = new List<string>();
report.timeFrame.AddRange(data);
break;
case "Received Date":
if (report.receivedDate == null) report.receivedDate = new List<string>();
report.receivedDate.AddRange(data);
break;
case "Service Date":
if (report.serviceDate == null) report.serviceDate = new List<string>();
report.serviceDate.AddRange(data);
break;
case "Adjustments":
if (report.adjustments == null) report.adjustments = new List<string>();
report.adjustments.AddRange(data);
break;
case "View":
if (report.view == null) report.view = new List<string>();
report.view.AddRange(data);
break;
case "SERVICE LINE":
if (report.serviceLine == null) report.serviceLine = new List<string>();
report.serviceLine.AddRange(data);
break;
case "SITE":
if (report.site == null) report.site = new List<string>();
report.site.AddRange(data);
break;
case "FILTER":
if (report.filter == null) report.filter = new List<string>();
report.filter.AddRange(data);
break;
case "Client ID":
if (report.clientId == null) report.clientId = new List<string>();
report.clientId.AddRange(data);
break;
}
}
}
}
}
public class Report
{
public string title { get; set; }
public string description { get; set; }
public string generated { get; set; }
public string name { get; set; }
public List<string> timeFrame { get; set; }
public List<string> receivedDate { get; set; }
public List<string> serviceDate { get; set; }
public List<string> adjustments { get; set; }
public List<string> view { get; set; }
public List<string> serviceLine { get; set; }
public List<string> site { get; set; }
public List<string> filter { get; set; }
public List<string> clientId { get; set; }
}
}