2013-05-14 67 views
7

我已经下载了一个流,作为一个字节[]'原始'大约是36MB。我然后再转换为字符串string.replace vs StringBuilder.replace内存

string temp = System.Text.Encoding.UTF8.GetString(raw) 

然后,我需要全部替换“\ n”和“\ r \ n”,所以我尝试

string temp2 = temp.Replace("\n","\r\n") 

但它抛出一个“内存不足“例外。然后我尝试使用StringBuilder创建一个新字符串:

string temp2 = new StringBuilder(temp).Replace("\n","\r\n").toString() 

并且它没有抛出异常。为什么首先会出现内存问题(我只在这里处理36MB),但为什么StringBuilder.Replace()在另一个不工作时工作?

+0

我看到了这个问题,但它更多与性能而不是内存使用。而且,这更像是“幕后发生了什么?”问题比“我该如何解决它?”一。 – Aeon2058 2013-05-14 12:13:52

回答

5

当你使用:

string temp2 = temp.Replace("\n","\r\n") 

在字符串TEMP“\ n”的每一场比赛,系统创建了一个更换一个新的字符串。

使用StringBuilder这不会发生,因为StringBuilder是可变的,因此您可以实际修改相同的对象而无需创建另一个对象。

实施例:

temp = "test1\ntest2\ntest3\n" 

随着第一方法(字符串)

string temp2 = temp.Replace("\n","\r\n") 

相当于

string aux1 = "test1\r\ntest2\ntest3\n" 
string aux2 = "test1\r\ntest2\r\ntest3\n" 
string temp2 = "test1\r\ntest2\r\ntest3\r\n" 

随着SECON方法(〜应变GBuilder的)

string temp2 = new StringBuilder(temp).Replace("\n","\r\n").toString() 

相当于

Stringbuilder aux = "test1\ntest2\ntest3\n" 
aux = "test1\r\ntest2\ntest3\n" 
aux = "test1\r\ntest2\r\ntest3\n" 
aux = "test1\r\ntest2\r\ntest3\r\n" 
string temp2 = aux.toString() 
+1

因此,如果我的字符串长36MB,并且说要替换50000个“\ n”,用string.Replace()这将需要36 * 50000MB来完成,这就是为什么有内存错误?不应该在aux1,aux2,aux3等上执行gc,因为它们不再需要? – Aeon2058 2013-05-14 12:21:06

+0

这看起来不正确。 https://github.com/fixdpt/shared-source-cli-2.0/blob/master/clr/src/vm/comstring.cpp#L1572提供了string.Replace运行的本地C++代码。 它首先迭代字符串,查找将被替换的所有子字符串索引。然后基于此分配恰到好处的内存量。然后它再次迭代字符串,将原始数据复制到新缓冲区,并在必要时进行替换。 – 2017-06-07 12:08:42

3

在从MSDN的StringBuilder:

大部分是修改这个类的一个实例方法 参考返回同一实例,并且您可以在该参考上调用方法或属性 。如果要编写链接连续操作的单个 语句,这可能很方便。

所以,当你调用String替换新对象(大数据-36MB)将被分配来创建新的字符串。但是StringBuilder访问相同的实例对象并且不会创建新的对象。

0

字符串在C#中是不可变的。如果使用string.replace()方法,系统将为每个替换项创建一个String对象。 StringBuilder类将帮助您避免创建对象。

1

存在内存压力的概念,意味着创建的临时对象越多,垃圾收集运行得越频繁。

所以: StringBuilder创建更少的临时对象并增加更少的内存压力。

StringBuilder Memory

更换

接下来,我们使用StringBuilder来循环替换字符。首先将字符串转换为StringBuilder,然后调用StringBuilder的方法。这是更快 - StringBuilder类型内部使用字符数组