10

我已经下载了一个大约 36MB 的 byte[] 'raw' 流。然后我将其转换为字符串

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

然后我需要用“\r\n”替换所有“\n”所以我尝试了

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

但它引发了“内存不足”异常。然后我尝试使用 StringBuilder 创建一个新字符串:

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

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

4

4 回答 4

7

当您使用:

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方法(StringBuilder)

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()
于 2013-05-14T09:38:25.073 回答
3

遵循MSDN的 StringBuilder :

大多数修改此类实例的方法都返回对同一实例的引用,您可以在引用上调用方法或属性。如果您想编写一个链接连续操作的语句,这会很方便。

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

于 2013-05-14T09:40:58.677 回答
1

有一个内存压力的概念,这意味着创建的临时对象越多,垃圾收集运行的频率就越高。

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

StringBuilder 内存

代替

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

于 2013-05-14T09:45:02.757 回答
0

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

于 2013-05-14T09:42:17.467 回答