C# 使C中的字符串连接更快#

C# 使C中的字符串连接更快#,c#,.net,string,c#-4.0,concatenation,C#,.net,String,C# 4.0,Concatenation,可能重复: 嗨 我有一个类似这样的代码片段,其中从文件中读取大量数据,并检查每个位置的值和字符串 这种字符串连接需要大量的时间和处理能力。是否有一种方法可以减少执行时间 重要提示:读取内容文件语法是不正确的,只需给出一个想法 string x; while (var < File.Length) { if (File.Content[var] == "A") { x += 1; } else { x += 0; } var++

可能重复:

我有一个类似这样的代码片段,其中从文件中读取大量数据,并检查每个位置的值和字符串

这种字符串连接需要大量的时间和处理能力。是否有一种方法可以减少执行时间

重要提示:读取内容文件语法是不正确的,只需给出一个想法

string x;

while (var < File.Length)
{
  if (File.Content[var] == "A")
  {
       x += 1;    
  }
  else
  {
     x += 0;
  }
  var++;
}
字符串x;
while(var
使用而不是字符串连接

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");
}
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();
}
StringBulder x=新的StringBuilder(10000);//根据需要调整容量
while(var
改用一个性能更好的字符串-每次在循环中使用字符串时都会创建一个新字符串,这会导致大量开销/垃圾收集,使用在循环外部创建的单个
StringBuilder
可以避免这种情况。

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
使用StringBuilder

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

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


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

示例代码如下所示:

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");
}
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");

-1:将来,提供一个更接近您实际操作的代码示例(实际上是C#)将有助于回答者编写比“使用
StringBuilder
”这一过于普遍的共识更好的解决方案。例如,你实际上是如何读取文件的,你是否真的在检查每个字符,你连接的字符串是否真的是单个字符,等等,实际上就是投票计数@Sudantha:因为这听起来像是StringBuilder的新手,可能值得一提的是,它只在执行“许多”连接时才有用。@Niklas,无论何时,只要您想以任何方式更改字符串(concat或deletation),并且不关心中间结果,它都是有用的。“即使你操作过一次。”怪物卡车:我有点不清楚。我所说的“有益的”,是指更多的表现。但请看Eric Lippert的回答:IMHO,StringBuilder几乎总是比String的“+”更妨碍可读性operator@Niklas,埃里克和我说的是同一件事(差不多)。他的陈述更像是一条经验法则,而我试图对其进行概括。我概括的关键是关于中间结果的一点。哦,是的,我同意可读性丢失了,因此如果它没有引起太多的问题,一个简单的concat实际上会提高开发人员的效率。不过,我确实理解正确——我也指的是性能。谢谢你的回答,我认为你可以给Alex一个正确的答案:)如果你读到的那部分内容分裂了一个潜在的匹配呢?