在c#中操作文本文件

本文关键字:作文本 文件 操作 | 更新日期: 2023-09-27 18:13:43

我被分配了一个项目,该项目需要一个c#控制台应用程序来操作文本文件。文本文件是一个bcp表转储文件。程序应该能够:

  1. 根据用户
  2. 给出的列将文件拆分为多个文件
  3. 从输出中包含或排除分割列

目前,我正在读取文件如下:

var groupQuery = from name in File.ReadAllLines(fileName)
                                .Skip(skipHeaderRow)
                             let n = name.Split(delimiterChars)
                             group name by n[index] into g
                             // orderby g.Key
                             select g;

我担心我可能会遇到内存问题,因为一些文件可以有超过200万条记录,每行约2617字节

在c#中操作文本文件

如果您确信您的程序只需要顺序访问… bcp转储文件,使用StreamReader类读取该文件。这个类针对顺序访问进行了优化,它将文件作为流打开,因此内存问题不应该困扰您。此外,您可以通过从该类的不同构造函数初始化来增加流的缓冲区大小,以便有更大的内存块可供处理。


如果你想随机访问你的文件碎片… go为内存映射文件。确保在文件的有限部分上创建视图访问器。在mmf链接中给出的示例代码解释了如何在大文件上创建小视图。


编辑:我有在我的答案中使用mmf的代码,但我现在已经删除了它,因为我意识到…尽管实际上group by是惰性的,但它也是一个非流 LINQ操作符。因此,它必须读取您的整个bcp转储,才能最终给出结果。这意味着:

  1. StreamReader显然是一个更好的方法为您 。确保您将缓冲区增加到最大可能;
  2. 你的LINQ将需要一些时间,当它被操作员击中组,只有在整个文件读取完成后才会恢复生命。

尝试使用Buffered Streams来读写文件,而不将它们完全加载到内存中。

using (FileStream fs = File.Open(inputFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) {
        using (StreamReader sr = new StreamReader(fs)) {
            string line = sr.ReadLine();
            string lineA = null;
            string lineB = null;
            while ((line != null)) {
                // Split your line here into lineA and lineB
                // and write using buffered writer.
                line = sr.ReadLine();
            }
        }
}

(离这里)

这个想法是一行一行地读取文件,而不是将整个东西加载到内存中,按照你想要的方式拆分它,然后将拆分的行逐行写入输出文件。

别白费力气了。考虑使用FileHelpers之类的库。

http://www.filehelpers.net/example/QuickStart/ReadWriteRecordByRecord/

var engine = new FileHelperAsyncEngine<Customer>();
using(engine.BeginReadFile(fileName))
{
    var groupQuery =
        from o in engine
        group name by o.CustomerId into g
        // orderby g.Key
        select g;   
    foreach(Customer cust in engine)
    {
        Console.WriteLine(cust.Name);
    }
}

你仍然会遇到组和排序函数的内存问题,因为所有的记录都需要在内存中进行分组和排序。