C#:将可变结构的 CSV 文件读入带有行计数器的数据表中
C#: Reading a variable structured CSV file into a datatable with a row counter
我正在尝试开发一种工具,可以将 CSV 文件导入到数据表中,数据表中的第一列是行计数器。
CSV 文件来自不同的客户,因此具有不同的结构。有些有 header 行;有些有几行 header 行;有些没有 header 行。他们也有不同的专栏。
到目前为止,我有下面的代码。
public void Import_CSV()
{
OpenFileDialog dialog = new OpenFileDialog();
dialog.Filter = "CSV Files (*.csv)|*.csv";
bool? result = dialog.ShowDialog();
if (result ?? false)
{
string[] headers;
string CSVFilePathName = dialog.FileName;
string delimSelect = cboDelimiter.Items.GetItemAt(cboDelimiter.SelectedIndex).ToString();
// If user hasn't selected a delimiter, assume comma
if (delimSelect == "")
{
delimSelect = ",";
}
string[] delimiterType = new string[] {cboDelimiter.Items.GetItemAt(cboDelimiter.SelectedIndex).ToString()};
DataTable dt = new DataTable();
// Read first line of file to get number of fields and create columns and column numbers in data table
using (StreamReader sr1 = new StreamReader(CSVFilePathName))
{
headers = sr1.ReadLine().Split(delimiterType, StringSplitOptions.None);
//dt.Columns.Add("ROW", typeof(int));
//dt.Columns["ROW"].AutoIncrement = true;
//dt.Columns["ROW"].AutoIncrementSeed = 1;
//dt.Columns["ROW"].AutoIncrementStep = 1;
int colCount = 1;
foreach (string header in headers)
{
dt.Columns.Add("C" + colCount.ToString());
colCount++;
}
}
using (StreamReader sr = new StreamReader(CSVFilePathName))
{
while (!sr.EndOfStream)
{
string[] rows = sr.ReadLine().Split(delimiterType, StringSplitOptions.None);
DataRow dr = dt.NewRow();
for (int i = 0; i < headers.Length; i++)
{
dr[i] = rows[i];
}
dt.Rows.Add(dr);
}
}
dtGrid.ItemsSource = dt.DefaultView;
txtColCount.Text = dtGrid.Columns.Count.ToString();
txtRowCount.Text = dtGrid.Items.Count.ToString();
}
}
这有效,因为它创建了列 headers(C1、C2....根据 csv 文件中的数量)然后写入行,但我想要在添加行时在最左侧添加一个带有行号的列。在代码中,您可以看到我注释掉了创建 auto-number 列的部分,但我完全不明白行是如何写入数据表的。如果我取消注释该部分,我会收到错误,因为 csv 文件中的第一列试图写入一个 int 字段。我知道您可以指定每一行中的哪个字段可以进入哪一列,但这在这里无济于事,因为此时这些列是未知的。我只需要它能够读取任何文件,无论结构如何,但使用行计数器。
希望这是有道理的。
您在问题中写道,取消注释添加第一列的代码会导致错误。这是因为你的循环:它从 0 开始,但第 0 列是你手动添加的。所以你只需要在你的循环中跳过它,从 1 开始。但是,源数组必须从第 0 个元素开始处理。
所以解决方案是:
首先,取消注释添加代码的行。
然后,在您的循环中,引入一个偏移量以保持第一列不变:
for (int i = 0; i < headers.Length; i++)
{
dr[i + 1] = rows[i];
}
我正在尝试开发一种工具,可以将 CSV 文件导入到数据表中,数据表中的第一列是行计数器。
CSV 文件来自不同的客户,因此具有不同的结构。有些有 header 行;有些有几行 header 行;有些没有 header 行。他们也有不同的专栏。
到目前为止,我有下面的代码。
public void Import_CSV()
{
OpenFileDialog dialog = new OpenFileDialog();
dialog.Filter = "CSV Files (*.csv)|*.csv";
bool? result = dialog.ShowDialog();
if (result ?? false)
{
string[] headers;
string CSVFilePathName = dialog.FileName;
string delimSelect = cboDelimiter.Items.GetItemAt(cboDelimiter.SelectedIndex).ToString();
// If user hasn't selected a delimiter, assume comma
if (delimSelect == "")
{
delimSelect = ",";
}
string[] delimiterType = new string[] {cboDelimiter.Items.GetItemAt(cboDelimiter.SelectedIndex).ToString()};
DataTable dt = new DataTable();
// Read first line of file to get number of fields and create columns and column numbers in data table
using (StreamReader sr1 = new StreamReader(CSVFilePathName))
{
headers = sr1.ReadLine().Split(delimiterType, StringSplitOptions.None);
//dt.Columns.Add("ROW", typeof(int));
//dt.Columns["ROW"].AutoIncrement = true;
//dt.Columns["ROW"].AutoIncrementSeed = 1;
//dt.Columns["ROW"].AutoIncrementStep = 1;
int colCount = 1;
foreach (string header in headers)
{
dt.Columns.Add("C" + colCount.ToString());
colCount++;
}
}
using (StreamReader sr = new StreamReader(CSVFilePathName))
{
while (!sr.EndOfStream)
{
string[] rows = sr.ReadLine().Split(delimiterType, StringSplitOptions.None);
DataRow dr = dt.NewRow();
for (int i = 0; i < headers.Length; i++)
{
dr[i] = rows[i];
}
dt.Rows.Add(dr);
}
}
dtGrid.ItemsSource = dt.DefaultView;
txtColCount.Text = dtGrid.Columns.Count.ToString();
txtRowCount.Text = dtGrid.Items.Count.ToString();
}
}
这有效,因为它创建了列 headers(C1、C2....根据 csv 文件中的数量)然后写入行,但我想要在添加行时在最左侧添加一个带有行号的列。在代码中,您可以看到我注释掉了创建 auto-number 列的部分,但我完全不明白行是如何写入数据表的。如果我取消注释该部分,我会收到错误,因为 csv 文件中的第一列试图写入一个 int 字段。我知道您可以指定每一行中的哪个字段可以进入哪一列,但这在这里无济于事,因为此时这些列是未知的。我只需要它能够读取任何文件,无论结构如何,但使用行计数器。
希望这是有道理的。
您在问题中写道,取消注释添加第一列的代码会导致错误。这是因为你的循环:它从 0 开始,但第 0 列是你手动添加的。所以你只需要在你的循环中跳过它,从 1 开始。但是,源数组必须从第 0 个元素开始处理。
所以解决方案是:
首先,取消注释添加代码的行。
然后,在您的循环中,引入一个偏移量以保持第一列不变:
for (int i = 0; i < headers.Length; i++)
{
dr[i + 1] = rows[i];
}