1.关于本文
今天写了个C#工具类CSVHelper,可以将CSV文件导入到DataTable中,也可以将DataTable中的数据导出到CSV文件里
2.制作CSV样本文档
我专门写了个VBA宏来制作CSV样本文档,代码如下:
Sub PrintMultiplicationTable()
For i = 1 To 9
For j = 1 To 9
Range(Chr(65 + i - 1) & j) = i & "*" & j & "=" & (i * j)
Next
Next
End Sub
生成的EXCEL表格如下:

保存成CSV格式的文件mt.csv,内容如下
1*1=1,2*1=2,3*1=3,4*1=4,5*1=5,6*1=6,7*1=7,8*1=8,9*1=9
1*2=2,2*2=4,3*2=6,4*2=8,5*2=10,6*2=12,7*2=14,8*2=16,9*2=18
1*3=3,2*3=6,3*3=9,4*3=12,5*3=15,6*3=18,7*3=21,8*3=24,9*3=27
1*4=4,2*4=8,3*4=12,4*4=16,5*4=20,6*4=24,7*4=28,8*4=32,9*4=36
1*5=5,2*5=10,3*5=15,4*5=20,5*5=25,6*5=30,7*5=35,8*5=40,9*5=45
1*6=6,2*6=12,3*6=18,4*6=24,5*6=30,6*6=36,7*6=42,8*6=48,9*6=54
1*7=7,2*7=14,3*7=21,4*7=28,5*7=35,6*7=42,7*7=49,8*7=56,9*7=63
1*8=8,2*8=16,3*8=24,4*8=32,5*8=40,6*8=48,7*8=56,8*8=64,9*8=72
1*9=9,2*9=18,3*9=27,4*9=36,5*9=45,6*9=54,7*9=63,8*9=72,9*9=81
另有一个文件mt2.csv,这个文件与前者的区别是在最前添加了一个标题行
A,B,C,D,E,F,G,H,I
3.关于CSVHelper类
CSVHelper类中有两个函数,分别是从CSV中读取数据和将数据打印到CSV中
1)public static DataTable ReadFromCSV(string path, bool hasTitle = false)
2)public static void SaveToCSV(DataTable dt, string path, bool hasTitle = false)
代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;
using System.IO;
namespace CSVTest
{
class CSVHelper
{
/// <summary>
/// 将CSV文件中内容读取到DataTable中
/// </summary>
/// <param name="path">CSV文件路径</param>
/// <param name="hasTitle">是否将CSV文件的第一行读取为DataTable的列名</param>
/// <returns></returns>
public static DataTable ReadFromCSV(string path, bool hasTitle = false)
{
DataTable dt = new DataTable(); //要输出的数据表
StreamReader sr = new StreamReader(path); //文件读入流
bool bFirst = true; //指示是否第一次读取数据
//逐行读取
string line;
while ((line = sr.ReadLine()) != null)
{
string[] elements = line.Split(',');
//第一次读取数据时,要创建数据列
if (bFirst)
{
for (int i = 0; i < elements.Length; i++)
{
dt.Columns.Add();
}
bFirst = false;
}
//有标题行时,第一行当做标题行处理
if (hasTitle)
{
for (int i = 0; i < dt.Columns.Count && i < elements.Length; i++)
{
dt.Columns[i].ColumnName = elements[i];
}
hasTitle = false;
}
else //读取一行数据
{
if (elements.Length == dt.Columns.Count)
{
dt.Rows.Add(elements);
}
else
{
//throw new Exception("CSV格式错误:表格各行列数不一致");
}
}
}
sr.Close();
return dt;
}
/// <summary>
/// 将DataTable内容保存到CSV文件中
/// </summary>
/// <param name="dt">数据表</param>
/// <param name="path">CSV文件地址</param>
/// <param name="hasTitle">是否要输出数据表各列列名作为CSV文件第一行</param>
public static void SaveToCSV(DataTable dt, string path, bool hasTitle = false)
{
StreamWriter sw = new StreamWriter(path);
//输出标题行(如果有)
if (hasTitle)
{
for (int i = 0; i < dt.Columns.Count; i++)
{
sw.Write(dt.Columns[i].ColumnName);
if (i != dt.Columns.Count - 1)
{
sw.Write(",");
}
}
sw.WriteLine();
}
//输出文件内容
for (int i = 0; i < dt.Rows.Count; i++)
{
for (int j = 0; j < dt.Columns.Count; j++)
{
sw.Write(dt.Rows[i][j].ToString());
if (j != dt.Columns.Count - 1)
{
sw.Write(",");
}
}
sw.WriteLine();
}
sw.Close();
}
}
}
4.Main函数调用
在Main函数中调用这两个函数,分别从mt.csv、mt2.csv中读取数据,并打印到output.csv和output2.csv里
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data;
namespace CSVTest
{
class Program
{
static void Main(string[] args)
{
//不带标题行的csv,读取与输出
DataTable dt = CSVHelper.ReadFromCSV("mt.csv");
CSVHelper.SaveToCSV(dt, "output.csv");
//带标题行的csv,读取与输出
DataTable dt2 = CSVHelper.ReadFromCSV("mt2.csv", true);
CSVHelper.SaveToCSV(dt2, "output2.csv", true);
//按任意键继续
Console.WriteLine("按任意键继续 ...");
Console.ReadKey();
Console.Write("\b ");
}
}
}
END
1469

被折叠的 条评论
为什么被折叠?



