csharp-code-csv文件解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;

class CsvUtil
{
/// <summary>
/// 将CSV数据转换为DataTable
/// </summary>
/// <param name="csvFilePath">csv文件路径</param>
/// <param name="isRowHead">是否将第一行作为字段名</param>
/// <returns></returns>
public static DataTable ToDataTable2(string csvFilePath, bool isRowHead)
{
DataTable dt = null;
if (File.Exists(csvFilePath))
{
string csvstr = File.ReadAllText(csvFilePath, Encoding.Default);
if (!string.IsNullOrEmpty(csvstr))
{
dt = ToDataTable(csvstr, isRowHead);
}
}
return dt;
}
/// <summary>
/// 将CSV数据转换为DataTable
/// </summary>
/// <param name="csv">包含以","分隔的CSV数据的字符串</param>
/// <param name="isRowHead">是否将第一行作为字段名</param>
/// <returns></returns>
public static DataTable ToDataTable(string csv, bool isRowHead)
{
DataTable dt = null;
if (!string.IsNullOrEmpty(csv))
{
dt = new DataTable();
string[] csvRows = csv.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
string[] csvColumns = null;
if (csvRows != null)
{
if (csvRows.Length > 0)
{
//第一行作为字段名,添加第一行记录并删除csvRows中的第一行数据
if (isRowHead)
{
csvColumns = FromCsvLine(csvRows[0]);
csvRows[0] = null;
for (int i = 0; i < csvColumns.Length; i++)
{
dt.Columns.Add(csvColumns[i]);
}
}
for (int i = 0; i < csvRows.Length; i++)
{
if (csvRows[i] != null)
{
csvColumns = FromCsvLine(csvRows[i]);
//检查列数是否足够,不足则补充
if (dt.Columns.Count < csvColumns.Length)
{
int columnCount = csvColumns.Length - dt.Columns.Count;
for (int c = 0; c < columnCount; c++)
{
dt.Columns.Add();
}
}
dt.Rows.Add(csvColumns);
}
}
}
}
}
return dt;
}
/// <summary>
/// 解析一行CSV数据
/// </summary>
/// <param name="csv">csv数据行</param>
/// <returns></returns>
public static string[] FromCsvLine(string csv)
{
List<string> csvLiAsc = new List<string>();
List<string> csvLiDesc = new List<string>();
if (!string.IsNullOrEmpty(csv))
{
//顺序超找
int lastIndex = 0;
int quotCount = 0;
//剩余的字符串
string lstr = string.Empty;
for (int i = 0; i < csv.Length; i++)
{
if (csv[i] == '"')
{
quotCount++;
}
else if (csv[i] == ',' && quotCount % 2 == 0)
{
csvLiAsc.Add(ReplaceQuote(csv.Substring(lastIndex, i - lastIndex)));
lastIndex = i + 1;
}
if (i == csv.Length - 1 && lastIndex < csv.Length)
{
lstr = csv.Substring(lastIndex, i - lastIndex + 1);
}
}
if (!string.IsNullOrEmpty(lstr))
{
//倒序超找
lastIndex = 0;
quotCount = 0;
string revStr = Reverse(lstr);
for (int i = 0; i < revStr.Length; i++)
{
if (revStr[i] == '"')
{
quotCount++;
}
else if (revStr[i] == ',' && quotCount % 2 == 0)
{
csvLiDesc.Add(ReplaceQuote(Reverse(revStr.Substring(lastIndex, i - lastIndex))));
lastIndex = i + 1;
}
if (i == revStr.Length - 1 && lastIndex < revStr.Length)
{
csvLiDesc.Add(ReplaceQuote(Reverse(revStr.Substring(lastIndex, i - lastIndex + 1))));
lastIndex = i + 1;
}
}
string[] tmpStrs = csvLiDesc.ToArray();
Array.Reverse(tmpStrs);
csvLiAsc.AddRange(tmpStrs);
}
}
return csvLiAsc.ToArray();
}
/// <summary>
/// 反转字符串
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
private static string Reverse(string str)
{
string revStr = string.Empty;
foreach (char chr in str)
{
revStr = chr.ToString() + revStr;
}
return revStr;
}
/// <summary>
/// 替换CSV中的双引号转义符为正常双引号,并去掉左右双引号
/// </summary>
/// <param name="csvValue">csv格式的数据</param>
/// <returns></returns>
private static string ReplaceQuote(string csvValue)
{
string rtnStr = csvValue;
if (!string.IsNullOrEmpty(csvValue))
{
//首尾都是"
Match m = Regex.Match(csvValue, "^\"(.*?)\"$");
if (m.Success)
{
rtnStr = m.Result("${1}").Replace("\"\"", "\"");
}
else
{
rtnStr = rtnStr.Replace("\"\"", "\"");
}
}
return rtnStr;
}
}