在练习过程中先后遇到了以下两种需求:
- 完整读取CSV文件,包括CSV文件的表头
- 只读取CSV文件内容,表头自定义添加
针对需求1,代码如下:
//*********************************csv2dt----读取csv表头方案**********************************************************
/// <summary>
/// 将Csv读入DataTable
/// </summary>
/// <param name="filePath">csv文件路径</param>
/// <param name="n">表示第n行是字段title,第n+1行是记录开始</param>
/// <param name="k">可选参数表示最后K行不算记录默认0</param>
public static DataTable csv2dt(string filePath, int n) //这个dt 是个空白的没有任何行列的DataTable
{
String csvSplitBy = "(?<=^|,)(\"(?:[^\"]|\"\")*\"|[^,]*)";
StreamReader reader = new StreamReader(filePath, System.Text.Encoding.Default, false);
int i = 0, m = 0;
reader.Peek();
DataTable dt = new DataTable();
while (reader.Peek() > 0)
{
m = m + 1;
string str = reader.ReadLine();
if (m >= n )
{
if (m == n ) //如果是字段行,则自动加入字段。
{
MatchCollection mcs = Regex.Matches(str, csvSplitBy);
foreach (Match mc in mcs)
{
dt.Columns.Add(mc.Value); //增加列标题
}
}
else
{
MatchCollection mcs = Regex.Matches(str, "(?<=^|,)(\"(?:[^\"]|\"\")*\"|[^,]*)");//正则表达式判断
i = 0;
System.Data.DataRow dr = dt.NewRow();
foreach (Match mc in mcs)
{
dr[i] = mc.Value;
//dr[i] = mc.Value.Replace("\"", "");//数列字符串自带的引号
i++;
}
dt.Rows.Add(dr); //DataTable 增加一行
}
}
}
return dt;
}
private void button1_Click(object sender, EventArgs e)//打开文件并传入ArrayList,此处不可以写返回,返回会报错
{
string str_filePath = Form1.OpenFile();//打开文件
if (str_filePath != "")//判断来的字符串是否为“”,因为在选择文件时如果点击取消,则会返回str="",测试过用!=null来判断,但会报错;
{
DataTable dt = Form1.csv2dt(@str_filePath, 1);
dataGridView1.DataSource = dt;//datatable数据显示
}
}
针对需求2,代码如下:
//*********************************csv2dt----自定义表头方案*********************************************
public static DataTable CreateDataTableHead(String[] str_DataTableHead)//创建一个空表,并建立表头
{
DataTable dt = new DataTable();
for (int i = 0; i < str_DataTableHead.Length; i++)
{
dt.Columns.Add(str_DataTableHead[i]);
}//遍历字段名作为表头
return dt;
}
/// <summary>
/// 将Csv读入DataTable
/// </summary>
/// <param name="filePath">csv文件路径</param>
/// <param name="n">表示第n行是字段title,第n+1行是记录开始</param>
/// <param name="k">可选参数表示最后K行不算记录默认0</param>
public static DataTable csv2dt(string filePath, int n, DataTable dt) //这个dt 是个空白的没有任何行列的DataTable
{
String csvSplitBy = "(?<=^|,)(\"(?:[^\"]|\"\")*\"|[^,]*)";
StreamReader reader = new StreamReader(filePath, System.Text.Encoding.Default, false);
int i = 0, m = 0;
reader.Peek();
while (reader.Peek() > 0)
{
m = m + 1;
string str = reader.ReadLine();
if (m >= n + 1)
{
if (m == n) //如果是字段行,则自动加入字段。
{
MatchCollection mcs = Regex.Matches(str, csvSplitBy);
foreach (Match mc in mcs)
{
dt.Columns.Add(mc.Value); //增加列标题
}
}
else
{
MatchCollection mcs = Regex.Matches(str, "(?<=^|,)(\"(?:[^\"]|\"\")*\"|[^,]*)");
i = 0;
System.Data.DataRow dr = dt.NewRow();
foreach (Match mc in mcs)
{
dr[i] = mc.Value.Replace("\"", "");//数列字符串自带的引号
i++;
}
dt.Rows.Add(dr); //DataTable 增加一行
}
}
}
return dt;
}
private void btn_inputFileForm_daogui1_Click(object sender, EventArgs e)//导入参数文件
{
string str_filePath = daogui.OpenFile();//打开文件
if (str_filePath != "")//判断来的字符串是否为“”,因为在选择文件时如果点击取消,则会返回str="",测试过用!=null来判断,但会报错;
{
String[] str_DataTableHead_daogui1 = { "A", "B", "C", "D" };
DataTable dt_TableHead_daogui1 = daogui.CreateDataTableHead(str_DataTableHead_daogui1);
daogui1_Para_dt = daogui.csv2dt(@str_filePath, 1, dt_TableHead_daogui1);//csv数据转换进入DataTable
ListOfPara listofpara = new ListOfPara();
listofpara.biaoshi_label_para.Text = "导轨";//此句与本功能无关,方便后面调用,做一标识
listofpara.Show();
listofpara.dataGridView_ListOfPara.DataSource = daogui1_Para_dt;//datatable数据显示
listofpara.dataGridView_ListOfPara.ClearSelection();
}
}
需求2相较于需求1,多了一个CreateDataTableHead方法,同时改变了CSV2dt方法中的参数取值范围,即可实现