【问题标题】:Make String concatenation faster in C# [duplicate]在 C# 中使字符串连接更快[重复]
【发布时间】:2011-09-04 04:36:38
【问题描述】:

可能重复:
What's the best string concatenation method using C#?

嗨,

我有一个像这样的代码 sn-p,其中从文件中读取大量数据内容并检查每个位置的某个值并连接一个字符串。

这种字符串连接需要大量时间和处理能力。有什么方法可以减少执行时间吗?

重要提示:阅读内容文件语法不正确只需给个思路

string x;

while (var < File.Length)
{
  if (File.Content[var] == "A")
  {
       x += 1;    
  }
  else
  {
     x += 0;
  }
  var++;
}

【问题讨论】:

  • -1:在未来,提供一个更接近您实际所做的代码示例(实际上是 C#)将帮助回答者编写比“使用”这一普遍共识更好的解决方案StringBuilder'。例如,你实际上是如何读取文件的,你是否真的在检查每个字符,你连接的字符串是否真的是单个字符,等等。

标签: c# .net string c#-4.0 concatenation


【解决方案1】:

使用StringBuilder 代替字符串连接。

StringBuilder 对象维护一个缓冲区以容纳新数据的串联。如果空间可用,则将新数据附加到缓冲区的末尾;否则,分配一个新的更大的缓冲区,将原始缓冲区中的数据复制到新缓冲区,然后将新数据附加到新缓冲区。

String 相反是不可变的,每次连接它都会创建一个新对象并丢弃旧对象,效率非常低。

另外,如果您知道结果将是巨大的,您可能需要提前为StringBuilder 设置高容量。这将减少缓冲区重新分配的次数。

使用你的伪代码看起来像这样:

StringBulder x = new StringBuilder(10000); // adjust capacity to your needs

while (var < File.Length)
{
   if(File.Content[var] == "A")
      x.Append("1"); // or AppendLine, or AppendFormat
   else
      x.Append("2");
}

【讨论】:

  • 其实就是计票!
  • @Sudantha:因为听起来你好像是 StringBuilder 的新手,所以值得一提的是,它只在进行“多”连接时才有用。
  • @Niklas,每当您想以任何方式(连接或删除)更改字符串并且不关心中间结果时,它都是有益的。即使您操作一次。
  • @Monster Truck:我有点不清楚。我所说的“有益”是指性能更高。但请在此处查看 Eric Lippert 的回答:stackoverflow.com/questions/3216786/… 恕我直言,与 String 的“+”运算符相比,StringBuilder 几乎总是妨碍可读性
  • @Niklas,Eric 和我在说同样的话(差不多)。他的陈述更像是一个拇指规则,而我试图概括它。我概括的关键是关于临时结果的一点。哦,是的,我确实同意可读性丢失了,因此,如果它不会造成太大的问题,一个简单的 concat 实际上会提高开发人员的效率。不过,我确实正确理解了有益——我也指的是性能。
【解决方案2】:

System.Text.StringBuilder 是您要在循环中用于字符串连接操作的类型。它会更有效率。在每次迭代期间对对象使用.Append(value)

StringBuilder builder = new StringBuilder();

// and inside your loop 
{
    if (blah)
        builder.Append("1");
    else
        builder.Append("0");
}

string output = builder.ToString(); // use the final result

【讨论】:

  • 感谢您的回答,我认为您可以正确回答 Alex :)
【解决方案3】:

使用 StringBuilder 代替,它会执行得更好 - 使用字符串,您每次在循环内创建一个新字符串,这会导致大量开销/垃圾收集,使用您在循环外创建的单个 StringBuilder你可以避免这种情况。

【讨论】:

    【解决方案4】:

    使用 StringBuilder,字符串在 .net 中是不可变的,这意味着连接会生成字符串的副本。

    Using the StringBuilder Class (MSDN)

    StringBuilder sb = new StringBuilder();
    sb.Append("1") // like so
    

    【讨论】:

      【解决方案5】:

      使用 StringBuilder。

      var sb = new StringBuilder();
      sb.Append("abc");
      sb.Append("def");
      var str = sb.ToString();
      

      【讨论】:

        【解决方案6】:

        当您逐字节读取文件时,可能需要很长时间。我建议您在循环中读取一个字节块(例如 1024 或 2048)。然后,在您阅读的块中,使用正则表达式来匹配您的角色,特别是如果您有一个非常大的文件。

        示例代码如下所示:

        private string GetFileData(string fileName, string matchChar)
        {
            StringBuilder x = new StringBuilder();
            int blockCount = 2048;
            int offset = 0;
            string pattern = matchChar;
            int k = -1;
            using (var sr = new System.IO.FileStream(fileName, System.IO.FileMode.Open))
            {
               while ((sr.CanRead) && (k != 0))
               {
                   byte[] bt = new byte[blockCount];
                   k = sr.Read(bt, 0, blockCount);
                   string so = System.Text.UTF8Encoding.UTF8.GetString(bt);
                   var m = new System.Text.RegularExpressions.Regex(pattern).Matches(so);
                   foreach (System.Text.RegularExpressions.Match item in m)
                   {
                       x.Append(item.Value);
                   }
               }
            }
            return x.ToString();
        }
        

        你可以这样称呼

        GetFileData(@"c:\matchtest.ono", "a");
        

        【讨论】:

        • 如果你读取的块分裂了一个潜在的匹配怎么办?
        猜你喜欢
        • 1970-01-01
        • 2013-05-10
        • 2013-09-14
        • 1970-01-01
        • 1970-01-01
        • 2013-09-18
        • 2017-01-20
        • 1970-01-01
        相关资源
        最近更新 更多