【问题标题】:Reading and writing very large text files in C#在 C# 中读取和写入非常大的文本文件
【发布时间】:2016-10-10 01:16:03
【问题描述】:

我有一个非常大的文件,差不多 2GB。我正在尝试编写一个进程来读取文件并在没有第一行的情况下将其写出。我几乎一次只能读写一行,这需要很长时间。我可以打开它,删除第一行并在 TextPad 中更快地保存它,尽管这仍然很慢。

我使用这段代码来获取文件中的记录数:

private long getNumRows(string strFileName)
{
    long lngNumRows = 0;
    string strMsg;

    try
    {
        lngNumRows = 0;
        using (var strReader = File.OpenText(@strFileName))
        {
            while (strReader.ReadLine() != null)
            {
                lngNumRows++;
            }

            strReader.Close();
            strReader.Dispose();
        }
    }
    catch (Exception excExcept)
    {
        strMsg = "The File could not be read: ";
        strMsg += excExcept.Message;
        System.Windows.MessageBox.Show(strMsg);
        //Console.WriteLine("Thee was an error reading the file: ");
        //Console.WriteLine(excExcept.Message);

        //Console.ReadLine();
    }

    return lngNumRows;
}

这只需几秒钟即可运行。当我添加以下代码时,它需要永远运行。难道我做错了什么?为什么写会增加这么多时间?关于如何使这更快的任何想法?

private void ProcessTextFiles(string strFileName)
{
    string strDataLine;
    string strFullOutputFileName;
    string strSubFileName;
    int intPos;
    long lngTotalRows = 0;
    long lngCurrNumRows = 0;
    long lngModNumber = 0;
    double dblProgress = 0;
    double dblProgressPct = 0;
    string strPrgFileName = "";
    string strOutName = "";
    string strMsg;
    long lngFileNumRows;

    try
    {
       using (StreamReader srStreamRdr = new StreamReader(strFileName))
        {
            while ((strDataLine = srStreamRdr.ReadLine()) != null)
            {
                lngCurrNumRows++;

                if (lngCurrNumRows > 1)
                {
                    WriteDataRow(strDataLine, strFullOutputFileName);
                }
            }

            srStreamRdr.Dispose();
        }
    }
    catch (Exception excExcept)
    {
        strMsg = "The File could not be read: ";
        strMsg += excExcept.Message;
        System.Windows.MessageBox.Show(strMsg);
        //Console.WriteLine("The File could not be read:");
        //Console.WriteLine(excExcept.Message);
    }
}

public void WriteDataRow(string strDataRow, string strFullFileName)
{
    //using (StreamWriter file = new StreamWriter(@strFullFileName, true, Encoding.GetEncoding("iso-8859-1")))
    using (StreamWriter file = new StreamWriter(@strFullFileName, true, System.Text.Encoding.UTF8))
    {
        file.WriteLine(strDataRow);
        file.Close();
    }
}

【问题讨论】:

  • 打开和关闭你想写的每一行的输出文件没有帮助
  • 正如 steve 所说,前面的例子没有写任何行
  • 为什么要统计行数?你能不计算行数并一次性删除第一个吗?

标签: c# .net wpf streamreader streamwriter


【解决方案1】:

不确定这会在多大程度上提高性能,但可以肯定的是,为您要编写的每一行打开和关闭输出文件并不是一个好主意。

而是只打开两个文件一次,然后直接写一行

using (StreamWriter file = new StreamWriter(@strFullFileName, true, System.Text.Encoding.UTF8))
using (StreamReader srStreamRdr = new StreamReader(strFileName))
{
    while ((strDataLine = srStreamRdr.ReadLine()) != null)
    {
        lngCurrNumRows++;

        if (lngCurrNumRows > 1)
           file.WriteLine(strDataRow);
    }
}

您还可以删除对lngCurrNumRow 的检查,只需在进入 while 循环之前进行空读取

strDataLine = srStreamRdr.ReadLine();
if(strDataLine != null)
{
    while ((strDataLine = srStreamRdr.ReadLine()) != null)
    {
           file.WriteLine(strDataRow);
    }
}

【讨论】:

    【解决方案2】:

    取决于您机器的内存。您可以尝试以下操作(我的大文件是“D:\savegrp.log”,我有一个 2gb 的文件在敲)这在我尝试时使用了大约 6gb 的内存

    int counter = File.ReadAllLines(@"D:\savegrp.log").Length;
    Console.WriteLine(counter);
    

    这取决于可用的内存..

    File.WriteAllLines(@"D:\savegrp2.log",File.ReadAllLines(@"D:\savegrp.log").Skip(1));
    Console.WriteLine("file saved");
    

    【讨论】:

    • 我试过 File.ReadAllLines 但我没有足够的内存来存放这个文件。
    • 谢谢史蒂夫,这就像一个魅力。我花了将近一个小时的时间和 file.WriteLine(strDataRow);只需几分钟。非常感谢大家的快速回复!
    • 你编译成64位了吗?我刚刚超过 2gb 的文件我的内存使用上升到 6gb
    • 请注意,史蒂夫的答案更好,因为它的内存低,但是,这很容易阅读..
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-04-30
    • 2016-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多