CsvHelper - 设置 header 行和数据行
CsvHelper - Set the header row and data row
我有这样的示例数据:
1 This is a random line in the file
2
3 SOURCE_ID|NAME|START_DATE|END_DATE|VALUE_1|VALUE_2
4
5 Another random line in the file
6
7
8
9
10 GILBER|FRED|2019-JAN-01|2019-JAN-31|ABC|DEF
11 ALEF|ABC|2019-FEB-01|2019-AUG-31|FBC|DGF
12 GILBER|FRED|2019-JAN-01|2019-JAN-31|ABC|TEF
13 FLBER|RED|2019-JUN-01|2019-JUL-31|AJC|DEH
14 GI|JOE|2020-APR-01|2020-DEC-31|GBC|DER
我无法保存对文件的更改。也就是说,我不能manipulate/clean消费前的原始文件。任何操作都需要在内存中即时完成。但是如果文件很大(例如,我目前正在测试一些超过 500 万条记录的文件)。
我正在使用CsvHelper
我已经参考了以下主题以获取指导:
Better way to skip extraneous lines at the start?
我想做的是:
- 设置 header 所在的行 = 3(我会知道 header 在哪里)
- 设置数据开始的行= 10(我会知道数据从哪里开始)
- 加载数据到datatable,显示到datagridview
如果我需要在将其传递到 CsvHelper 之前执行流操作的组合,那么也请告诉我这是否是缺失的部分? (以及任何关于我如何在一个代码块下实际实现这一目标的帮助,我将不胜感激)
到目前为止,我已经想出了以下内容:
string filepath = Path.Combine(txtTst04_File_Location.Text, txtTst04_File_Name.Text);
using (var reader = new StreamReader(filepath))
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
// skip rows to get the header
for (int i = 0; i < 4; i++)
{
csv.Read();
}
csv.Configuration.Delimiter = "|"; // Set delimiter
csv.Configuration.IgnoreBlankLines = false;
csv.Configuration.HasHeaderRecord = true;
// how do I set the row where the actual data starts?
using (var dr = new CsvDataReader(csv))
{
var dt = new DataTable();
dt.Load(dr);
dgvTst04_View.DataSource = dt; // Set datagridview source to datatable
}
}
我得到以下结果:
如果您希望我详细说明任何一点,请告诉我。
谢谢!
编辑:
此处创建的新链接 post 试图解决相同的问题 objective,但方式不同,但出现新错误:
Filestream and datagridview memory issue with CsvHelper
我可以让它与 ShouldSkipRecord
一起工作。唯一的问题是如果任何随机行有一个“|”,它将失败其中包含分隔符。
using (var reader = new StreamReader(filepath))
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
csv.Configuration.Delimiter = "|"; // Set delimiter
csv.Configuration.ShouldSkipRecord = row => row.Length == 1;
using (var dr = new CsvDataReader(csv))
{
var dt = new DataTable();
dt.Load(dr);
dgvTst04_View.DataSource = dt; // Set datagridview source to datatable
}
}
如果您知道有多少列,则可以将其设置为跳过列数少于该列的所有行。
csv.Configuration.ShouldSkipRecord = row => row.Length < 6;
我想出了另一种方法,允许您跳过行到 header,然后跳到记录。
using (var reader = new StreamReader(filepath))
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
csv.Configuration.Delimiter = "|"; // Set delimiter
csv.Configuration.IgnoreBlankLines = false;
// skip to header
for (int i = 0; i < 3; i++)
{
csv.Read();
}
csv.ReadHeader();
var headers = csv.Context.HeaderRecord;
// skip to records
for (int i = 0; i < 6; i++)
{
csv.Read();
}
var dt = new DataTable();
foreach (var header in headers)
{
dt.Columns.Add(header);
}
while (csv.Read())
{
var row = dt.NewRow();
for (int i = 0; i < headers.Length; i++)
{
row[i] = csv.GetField(i);
}
dt.Rows.Add(row);
}
}
我有这样的示例数据:
1 This is a random line in the file
2
3 SOURCE_ID|NAME|START_DATE|END_DATE|VALUE_1|VALUE_2
4
5 Another random line in the file
6
7
8
9
10 GILBER|FRED|2019-JAN-01|2019-JAN-31|ABC|DEF
11 ALEF|ABC|2019-FEB-01|2019-AUG-31|FBC|DGF
12 GILBER|FRED|2019-JAN-01|2019-JAN-31|ABC|TEF
13 FLBER|RED|2019-JUN-01|2019-JUL-31|AJC|DEH
14 GI|JOE|2020-APR-01|2020-DEC-31|GBC|DER
我无法保存对文件的更改。也就是说,我不能manipulate/clean消费前的原始文件。任何操作都需要在内存中即时完成。但是如果文件很大(例如,我目前正在测试一些超过 500 万条记录的文件)。
我正在使用CsvHelper
我已经参考了以下主题以获取指导:
Better way to skip extraneous lines at the start?
我想做的是:
- 设置 header 所在的行 = 3(我会知道 header 在哪里)
- 设置数据开始的行= 10(我会知道数据从哪里开始)
- 加载数据到datatable,显示到datagridview
如果我需要在将其传递到 CsvHelper 之前执行流操作的组合,那么也请告诉我这是否是缺失的部分? (以及任何关于我如何在一个代码块下实际实现这一目标的帮助,我将不胜感激)
到目前为止,我已经想出了以下内容:
string filepath = Path.Combine(txtTst04_File_Location.Text, txtTst04_File_Name.Text);
using (var reader = new StreamReader(filepath))
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
// skip rows to get the header
for (int i = 0; i < 4; i++)
{
csv.Read();
}
csv.Configuration.Delimiter = "|"; // Set delimiter
csv.Configuration.IgnoreBlankLines = false;
csv.Configuration.HasHeaderRecord = true;
// how do I set the row where the actual data starts?
using (var dr = new CsvDataReader(csv))
{
var dt = new DataTable();
dt.Load(dr);
dgvTst04_View.DataSource = dt; // Set datagridview source to datatable
}
}
我得到以下结果:
如果您希望我详细说明任何一点,请告诉我。
谢谢!
编辑:
此处创建的新链接 post 试图解决相同的问题 objective,但方式不同,但出现新错误: Filestream and datagridview memory issue with CsvHelper
我可以让它与 ShouldSkipRecord
一起工作。唯一的问题是如果任何随机行有一个“|”,它将失败其中包含分隔符。
using (var reader = new StreamReader(filepath))
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
csv.Configuration.Delimiter = "|"; // Set delimiter
csv.Configuration.ShouldSkipRecord = row => row.Length == 1;
using (var dr = new CsvDataReader(csv))
{
var dt = new DataTable();
dt.Load(dr);
dgvTst04_View.DataSource = dt; // Set datagridview source to datatable
}
}
如果您知道有多少列,则可以将其设置为跳过列数少于该列的所有行。
csv.Configuration.ShouldSkipRecord = row => row.Length < 6;
我想出了另一种方法,允许您跳过行到 header,然后跳到记录。
using (var reader = new StreamReader(filepath))
using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
{
csv.Configuration.Delimiter = "|"; // Set delimiter
csv.Configuration.IgnoreBlankLines = false;
// skip to header
for (int i = 0; i < 3; i++)
{
csv.Read();
}
csv.ReadHeader();
var headers = csv.Context.HeaderRecord;
// skip to records
for (int i = 0; i < 6; i++)
{
csv.Read();
}
var dt = new DataTable();
foreach (var header in headers)
{
dt.Columns.Add(header);
}
while (csv.Read())
{
var row = dt.NewRow();
for (int i = 0; i < headers.Length; i++)
{
row[i] = csv.GetField(i);
}
dt.Rows.Add(row);
}
}