如何使我的StreamWriter更快

本文关键字:更快 StreamWriter 我的 何使 | 更新日期: 2023-09-27 18:20:35

我有这样的C#代码:

string strFilePath = @
"E:'input.txt";
string strFilePath2 = @
"E:'output.txt";
const int BufferSize = 65536; // 64 Kilobytes
FileStream fs = new FileStream(strFilePath2, FileMode.OpenOrCreate);
using(StreamWriter sw = new StreamWriter(fs)) {
    for (int ww = 0; ww < File.ReadLines(strFilePath).Count(); ww++) {
        string tx2 = GetLine(strFilePath, ww).Replace("||", "| |");
        var first = String.Join("", tx2.TakeWhile(c => Char.IsDigit(c) || c == '|' || c == '-'));
        var third = String.Join("", tx2.Reverse().TakeWhile(c => Char.IsDigit(c) || c == '|' || c == '-').Reverse());
        var second = tx2.Replace(first, "").Replace(third, "");
        string awal = first.ToString();
        string dua = third.ToString();
        string gabung = (awal + dua).Replace("||", "|") + Environment.NewLine;
        string[] pdua = dua.Split('|');
        int totalkanan = int.Parse(pdua[1]) + int.Parse(pdua[2]) + int.Parse(pdua[3]) + int.Parse(pdua[4]) + int.Parse(pdua[5]) + int.Parse(pdua[6]) + int.Parse(pdua[7]) + int.Parse(pdua[8]) + int.Parse(pdua[9]) + int.Parse(pdua[10]) + int.Parse(pdua[11]) + int.Parse(pdua[12]) + int.Parse(pdua[13]) + int.Parse(pdua[14]) + int.Parse(pdua[15]) + int.Parse(pdua[16]) + int.Parse(pdua[17]) + int.Parse(pdua[18]) + int.Parse(pdua[19]);
        if (totalkanan > 0) {
            sw.Write(gabung);
        }
    }       
}

获取线路方法:

string GetLine(string fileName, int line)
{
 using (var sr = new StreamReader(fileName))
    {
      sr.ReadLine();
      for (int i = 1; i < line; i++)
      sr.ReadLine();
      return sr.ReadLine();
    }
}

输入示例:

937|41|0|0|0|0|484|0|0|0|0|0|0|0|20||1|First lesson is when you'll be tested on your knowledge of the Elements of Darkness. Your task is to go get 20 Darkness elements from the Bale professors at the Zone of Darkness Elements.|2582|4342|1|0|0|0|0|470|0|0|0|0|0|0|0|0|0|0|0|
937|42|4335|1|0|0|470|0|0|0|0|0|0|0|2|Pass the test.|1||0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
937|43|0|0|0|0|483|0|0|0|0|0|0|0|42||1|There are no more tests to take.|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
937|44|7928|20|4348|1|481|0|0|0|0|0|0|0|42||1|Congratulations on your completion of all the lessons! Come back in a little while to receive your diploma.|2583|7928|-20|4348|-1|0|0|483|0|0|0|0|0|0|0|0|0|0|0|
937|45|7927|20|4347|1|479|0|0|0|0|0|0|0|42||1|Very nice~! Next, you'll be tested on the Elements of light.|2584|7927|-20|4347|-1|0|0|481|0|0|0|0|0|0|0|0|0|0|0|
937|46|7926|20|4346|1|477|0|0|0|0|0|0|0|42||1|Very nice~! Next, you'll be tested on the Elements of light.|2585|7926|-20|4346|-1|0|0|479|0|0|0|0|0|0|0|0|0|0|0|

输出:

937|41|0|0|0|0|484|0|0|0|0|0|0|0|20|2582|4342|1|0|0|0|0|470|0|0|0|0|0|0|0|0|0|0|0|
937|42|4335|1|0|0|470|0|0|0|0|0|0|0|2|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
937|43|0|0|0|0|483|0|0|0|0|0|0|0|42|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
937|44|7928|20|4348|1|481|0|0|0|0|0|0|0|42|2583|7928|-20|4348|-1|0|0|483|0|0|0|0|0|0|0|0|0|0|0|
937|45|7927|20|4347|1|479|0|0|0|0|0|0|0|42|2584|7927|-20|4347|-1|0|0|481|0|0|0|0|0|0|0|0|0|0|0|
937|46|7926|20|4346|1|477|0|0|0|0|0|0|0|42|2585|7926|-20|4346|-1|0|0|479|0|0|0|0|0|0|0|0|0|0|0|

这个程序正在运行,但问题是当输入文件有17k++行时,写入进度非常慢,但当输入文件只有4k+行时只有大约10秒,逻辑是为什么4k需要10秒,而17k超过5分钟?有什么解决这个问题的建议吗?提前谢谢!

如何使我的StreamWriter更快

您的GetLine()方法必须读取整个文件(直到有问题的行),每次读取一行。

正因为如此,您将看到性能呈指数级下降。

为什么不边读边读每一行呢?

string strFilePath = @"E:'input.txt";
string strFilePath2 = @"E:'output.txt";
const int BufferSize = 65536; // 64 Kilobytes
using (StreamWriter sw = new StreamWriter(fs))
{
    foreach (var line in File.ReadLines(strFilePath))
    {
        string tx2 = line.Replace("||", "| |");
        var first = String.Join("", tx2.TakeWhile(c => Char.IsDigit(c) || c == '|' || c == '-'));
        var third = String.Join("", tx2.Reverse().TakeWhile(c => Char.IsDigit(c) || c == '|' || c == '-').Reverse());
        var second = tx2.Replace(first, "").Replace(third, "");
        string awal = first.ToString();
        string dua = third.ToString();
        string gabung = (awal + dua).Replace("||", "|") + Environment.NewLine;
        string[] pdua = dua.Split('|');
        int totalkanan = int.Parse(pdua[1]) + int.Parse(pdua[2]) + int.Parse(pdua[3]) + int.Parse(pdua[4]) + int.Parse(pdua[5]) + int.Parse(pdua[6]) + int.Parse(pdua[7]) + int.Parse(pdua[8]) + int.Parse(pdua[9]) + int.Parse(pdua[10]) + int.Parse(pdua[11]) + int.Parse(pdua[12]) + int.Parse(pdua[13]) + int.Parse(pdua[14]) + int.Parse(pdua[15]) + int.Parse(pdua[16]) + int.Parse(pdua[17]) + int.Parse(pdua[18]) + int.Parse(pdua[19]);
        if (totalkanan > 0)
        {
            sw.Write(gabung);
        }
    }
}

您正在以低效的方式进行大量字符串操作,这将导致大量分配,并导致大量垃圾收集,这两种情况都会减慢您的速度。

它还看起来像是读取一次文件以获得行数,然后每行重新读取该文件以从文件中获得下一行!

File类还有其他更有效的方法,可以这样做:

int lineNumber = 0;
foreach (var line in File.ReadLines(path))
{
    lineNumber++;
    // process line
}

还知道数组从索引0开始吗,pdua[1]是数组中的第二项