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