C#CSV动态拆分

时间:2011-10-28 04:39:16

标签: c# .net linq csv streamreader

我有多个1.5 GB CSV文件,其中包含来自服务提供商的客户的多个帐户的帐单信息。我正在尝试将大型CSV文件拆分为较小的块,以便处理和格式化其中的数据。

我不想推出自己的CSV解析器,但这是我还没有看到的东西所以如果我错了请纠正我。 1.5GB文件包含以下顺序的信息:帐户信息,帐号,帐单日期,交易,Ex gst,Inc gst,类型和其他行。

请注意,此处的BillDate表示发票的生成日期,因此偶尔我们在同一个CSV中有两个以上的帐单日期。

票据按以下方式分组:帐号>账单日期>交易。

有些帐户有10行交易详情,有些帐户有超过300,000行交易详情。一个1.5GB的大型CSV文件包含大约800万行数据(之前我使用过UltraEdit)来将粘贴切割成更小的块,但这已经变得非常低效且耗时。

我只是想在我的WinForm中加载大型CSV文件,点击一个按钮,这会将这些大文件拆分成不超过250,000行的块,但有些账单实际上大于250,000行,在这种情况下保留它们因为无论如何都要订购,因此不需要在多个文件中拆分一个帐户。此外,我不想在CSV中使用多个帐单日期,在这种情况下,拆分器可以创建另一个额外拆分。

我已经拥有一个WinForm应用程序,可以在VS C#2010中自动在较小的文件中格式化CSV。

实际上是否可以处理这个非常大的CSV文件?我一直在尝试加载大文件,但MemoryOutOfException是一个烦恼,因为它每次崩溃,我不知道如何解决它。我愿意接受建议。

以下是我认为我应该做的事情:

  • 加载大型CSV文件(但由于OutOfMemoryException而失败)。怎么解决这个?
  • 按帐户名,帐单日期分组数据,并计算每个组的行数。
  • 然后创建一个整数数组。
  • 将这个整数数组传递给文件拆分器进程,该进程将获取这些数组并写入数据块。

任何建议都将不胜感激。

感谢。

4 个答案:

答案 0 :(得分:2)

您可以使用CsvReader来流式传输和解析数据,而无需一次性将其全部加载到内存中。

答案 1 :(得分:1)

是的...内存不足将发生巨大的文件。你需要认真对待你的情况。

与大多数问题一样,将所有内容分解为步骤。

之前我遇到过类似情况(CSV格式的大型数据文件,需要处理等)。

我做了什么:

制作程序套件的第1步或其他任何东西,只需将大文件剪切成许多较小的文件。我打破了5GB压缩的PGP加密文件(在解密之后......这是另一个令人头痛的问题)到很多小块。你可以做一些简单的事情,比如顺序编号(即001,002,003 ......)

然后创建一个应用程序来进行INPUT处理。这里没有真正的商业逻辑。在业务逻辑方面,我非常讨厌FILE IO,我喜欢数据在一个漂亮的SQL Server DB中的温暖模糊感。这就是我。我创建了一个线程池并且有N个线程(比如5,你决定你的机器可以处理多少)读取你创建的.csv部分文件。

每个线程读取一个文件。一对一的关系。因为它是文件I / O,所以请确保您不会同时运行太多。每个线程执行相同的基本操作。读取数据,将其置于db(表格式)的基本结构中,执行大量插入,然后结束线程。我使用LINQ to SQL,因为一切都是强类型的,什么不是,但每个都是自己的。 db设计越好,以后做逻辑就越好。

在所有线程执行完毕后,您将拥有数据库中原始CSV的所有数据。现在,您可以完成所有业务逻辑,并从那里做任何事情。不是最漂亮的解决方案,但考虑到我的情况/数据流/大小/要求,我被迫开发。你可能会选择完全不同的东西。只是分享我猜。

答案 2 :(得分:0)

您可以使用external sort。我想你必须在文件中进行初始传递以识别正确的行边界,因为CSV记录可能不是固定长度。

希望您可以使用一些现成的.NET外部排序实现。

答案 3 :(得分:0)

Microsoft.VisualBasic.FileIO命名空间中有一个非常有用的类,我用它来处理CSV文件 - TextFieldParser Class

它可能对大文件大小没有帮助,但它是内置的并处理引用和非引用字段(即使混合在同一行中)。我在工作中的项目中曾经使用过几次。

尽管有汇编名称,但可以与C#一起使用,以防你想知道。