http://hi.baidu.com/hyperpc/blog/item/830c470f0a0f23f537d1224f.html
在小批量数据导入的时候,最常用的就是使用excel工具,将数据保存为xls或csv文件,然后上传到服务器,然后读取出来通过数据库访问类的相关方法更新到数据库中。对于如何读取xls文件的方法,网上太多了,使用excel对象或ole db/odbc连接都行。对于csv文件,其中有一种方式就是通过文件流,将它作为文本读取出来,这其中会遇到一点小意外。
我们知道,使用excel工具保存成csv文件时有几个规则:
1、每一行的单元格内容之间用逗号分隔。
2、如果单元格的内容本身有逗号,这个单元格的内容将会用引号包含。
3、如果单元格的内容本身有引号,
引号不在首或尾,这个单元格内容不会被引号包含。
引号在首或尾,这个单元格内容会被引号包含且原来首尾的引号会被转义。
所以对于这样的内容,直接按逗号或引号使用split方法明显不合适,需要预先处理一下。办法很多,最容易想到的就是用正则过滤掉本身带逗号或引号的内容,剩下的再按逗号split就方便了,我将csv文件中的每一行获取出来存放到一个键值对的集合中,为了保证前后顺序一致,使用SortedList,这里用控制台程序示例一下:
1
string
s
=
string
.Empty;
2
string
src
=
string
.Empty;
3
SortedList sl
=
new
SortedList();
4
StreamReader fs
=
new
StreamReader(
new
FileStream(
"demo
.csv
"
, FileMode.Open, FileAccess.Read), Encoding.GetEncoding(
"
gb2312
"
));
5
while
(
!
string
.IsNullOrEmpty(s
=
fs.ReadLine()))
6
{
7
if
(
!
string
.IsNullOrEmpty(s))
8
{
9
Console.WriteLine(s);
10
src
=
s.Replace(
"
\
"
\
""
,
"
'
"
);
11
MatchCollection col
=
Regex.Matches(src,
"
,\
"
([
^
\
"
]+)\
"
,
"
, RegexOptions.ExplicitCapture);
12
IEnumerator ie
=
col.GetEnumerator();
13
while
(ie.MoveNext())
14
{
15
string
patn
=
ie.Current.ToString();
16
int
key
=
src.Substring(
0
, src.IndexOf(patn)).Split(
'
,
'
).Length;
17
if
(
!
sl.ContainsKey(key))
18
{
19
sl.Add(key, patn.Trim(
new
char
[] {
'
,
'
,
'
"
'
}).Replace(
"
'
"
,
"
\
""
));
20
src
=
src.Replace(patn,
"
,,
"
);
21
}
22
}
23
24
string
[] arr
=
src.Split(
'
,
'
);
25
for
(
int
i
=
0
; i
<
arr.Length; i
++
)
26
{
27
if
(
!
sl.ContainsKey(i))
28
sl.Add(i, arr[i]);
29
}
30
31
IDictionaryEnumerator ienum
=
sl.GetEnumerator();
32
while
(ienum.MoveNext())
33
{
34
Console.WriteLine(
string
.Format(
"
{0}:{1}
"
, ienum.Key, ienum.Value.ToString().Replace(
"
'
"
,
"
\
""
)));
35
}
36
sl.Clear();
37
src
=
string
.Empty;
38
}
39
Console.Read();
40
}
41
fs.Close();