请教高手:关于100万条的大CSV文件,具有容错性的读取方法?

ThankU 2011-10-12 07:13:12
一个CSV文件大概有100万条数据需要处理,用分号;分割,比如下面的例子:
id;name;class;email;tel
000001;zhao;A;zhao@test.com;12345677
000002;qian;A;qian@test.com;12345678
000003;sun;C;sun@test.com;12345679
000004;li;B;li@test.com;12345680

现在需要用程序把他们读出,(然后根据ID插入/更新到另一个系统)

问题是100万条数据,用什么方法读取更高效?是一次性加载到一个LIST里面然后在执行插入/更新操作呢?还是一条一条的读取在执行插入/更形操作?

还有一个很重要的要求,就是假若插入/更新操作有问题,那么要求系统记录下来出现问题的ID和出现的问题,并继续下一条操作。

求源代码(插入/更新操作可以直接用文字注明)
...全文
389 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
sdl2005lyx 2011-10-14
  • 打赏
  • 举报
回复
"不对啊,
这个csv文件的第一行是行名,应该被忽略掉的;"
第一行一看就知道是列名,读起来也没关系。 List<String[]> ls;
无非在你使用的时候从1的索引开始!列名称留着,说不定到时还有用途。。。
ThankU 2011-10-14
  • 打赏
  • 举报
回复
bulk insert c#??
freemangood 2011-10-14
  • 打赏
  • 举报
回复
+关注,等待分享结果!!
sdl2005lyx 2011-10-14
  • 打赏
  • 举报
回复
那你把3楼和我的结合起来,就是全部的答案!
不过,我这类也有一个封装好的读的方法,给你参考:

public static List<String[]> ReadCSV(string filePathName)
{
List<String[]> ls = new List<String[]>();
StreamReader fileReader=new StreamReader(filePathName);
string strLine="";
while (strLine != null)
{
strLine = fileReader.ReadLine();
if (strLine != null && strLine.Length>0)
{
ls.Add(strLine.Split(','));
//Debug.WriteLine(strLine);
}
}
fileReader.Close();
return ls;
}
YuccaWei 2011-10-14
  • 打赏
  • 举报
回复
我之前遇到过类似情况,使用的bulk Insert (具体用法你可以百度一下)
例如先把数据在程序里整理了一下,然后写入文件A.txt,然后数据库调用bulkinsert 一次性写入
经测试40万的数据量7秒就搞定
ThankU 2011-10-14
  • 打赏
  • 举报
回复
不对啊,
这个csv文件的第一行是行名,应该被忽略掉的;
而且读取文件出错的时候,记录下出错的id和错误信息,然后继续读取下一行数据。

目前的程序直接退出了。
sdl2005lyx 2011-10-13
  • 打赏
  • 举报
回复
楼主,3楼主的方法基本能解决读的问题!
有个问题,如果发现有你所说的错误,需要遍历时改过来吗?
如果需要把改写好好也存到csv里面,就还需要一个写的方法:

public static void WriteCSV(string filePathName,bool append, List<String[]> ls)
{
StreamWriter fileWriter=new StreamWriter(filePathName,append,Encoding.Default);
foreach(String[] strArr in ls)
{
fileWriter.WriteLine(String.Join (“;",strArr) );
}
fileWriter.Flush();
fileWriter.Close();

}
Herbert 2011-10-13
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 thanku 的回复:]

应该可以,但是和我需求的不太一样,这样吧,把错误的id和message写在 error.csv 里面可以么?

比如error.csv

error id; error message
2; id有误
1034; email有误
...
[/Quote]

自己组织一下
ThankU 2011-10-13
  • 打赏
  • 举报
回复
//有个问题,如果发现有你所说的错误,需要遍历时改过来吗?
不需要,只需要记录错误数据的行号和错误信息即可。
ThankU 2011-10-13
  • 打赏
  • 举报
回复
应该可以,但是和我需求的不太一样,这样吧,把错误的id和message写在 error.csv 里面可以么?

比如error.csv

error id; error message
2; id有误
1034; email有误
...

ARNEBEAR 2011-10-13
  • 打赏
  • 举报
回复
3楼的不行吗?
ThankU 2011-10-12
  • 打赏
  • 举报
回复
请高手就我的问题回答,需要源代码测试。。。
非常感谢!
vrhero 2011-10-12
  • 打赏
  • 举报
回复
CSV是标准的odbc数据源,就是个比较差的文件型数据库...直接ADO.NET查询就是了,没啥难度...
Herbert 2011-10-12
  • 打赏
  • 举报
回复

static void Main(string[] args)
{
string path = "data.csv";
try
{
StreamReader sr = new StreamReader(path);
string line;
while ((line = sr.ReadLine()) != null)
{
string[] arrStr = line.Split(';');
if (arrStr.Length != 5)
{
throw new ApplicationException("列数有误:" + line);
}
string aaaa = arrStr[0];
if(!Regex.IsMatch(aaaa,"^\\d{6}$"))
{
throw new ApplicationException("id有误:" + arrStr[0]);
}
if (!Regex.IsMatch(arrStr[2], "^[A-Z]$"))
{
throw new ApplicationException("class有误:" + arrStr[2]);
}
if (!Regex.IsMatch(arrStr[3], @"^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$"))
{
throw new ApplicationException("email有误:" + arrStr[3]);
}
// ......
Console.WriteLine(line);
}

sr.Dispose();
sr.Close(); // 关闭流
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}

Console.ReadKey();
}
啊的发哦 2011-10-12
  • 打赏
  • 举报
回复
“出现问题的ID和出现的问题”

这个比较恶心,你去SQL版咨询下。

别的问题点都很容易,先把这个关键点弄掉吧。
dybbuk 2011-10-12
  • 打赏
  • 举报
回复
用内存映射,比如http://www.cnblogs.com/criedshy/archive/2010/06/13/1757826.html
感觉出错的记录应该还要包括错误条目在文件的偏移

110,473

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧