Thi*_*iru 11 c# stringbuilder tostring streamwriter .net-2.0
我创建了一个StringBuilder长度"132370292",当我尝试使用ToString()它抛出的方法获取字符串OutOfMemoryException.
StringBuilder SB = new StringBuilder();
for(int i =0; i<=5000; i++)
{
SB.Append("Some Junk Data for testing. My Actual Data is created from different sources by Appending to the String Builder.");
}
try
{
string str = SB.ToString(); // Throws OOM mostly
Console.WriteLine("String Created Successfully");
}
catch(OutOfMemoryException ex)
{
StreamWriter sw = new StreamWriter(@"c:\memo.txt", true);
sw.Write(SB.ToString()); //Always writes to the file without any error
Console.WriteLine("Written to File Successfully");
}
Run Code Online (Sandbox Code Playgroud)
创建新字符串时OOM的原因是什么?为什么在写入文件时它不会抛出OOM?
机器详细信息:64位,Windows-7,2GB RAM,.NET 2.0版
Jon*_*eet 19
创建新字符串时OOM的原因是什么
因为内存不足 - 或者至少CLR无法分配具有您请求的大小的对象.这真的很简单.如果要避免错误,请不要尝试创建不适合内存的字符串.请注意,即使您有大量内存,即使您运行的是64位CLR,也可以创建可以创建的对象大小.
为什么它在写入文件时不会抛出OOM?
因为你有比内存更多的磁盘空间.
我很确定代码并不完全像你描述的那样.这行无法编译:
sw.write(SB.ToString());
Run Code Online (Sandbox Code Playgroud)
...因为方法Write不是write.如果你真的打电话SB.ToString(),那就像失败一样str = SB.ToString().
它似乎更容易,你实际上是写入文件以流方式,如
using (var writer = File.CreateText(...))
{
for (int i = 0; i < 5000; i++)
{
writer.Write(mytext);
}
}
Run Code Online (Sandbox Code Playgroud)
这样你就不需要在内存中有大量的文本 - 它只是将它写入磁盘,可能有一些缓冲,但不足以引起内存问题.
解决方法:假设您希望将存储在StringBuilder中的大字符串写入StreamWriter,我会以这种方式编写以避免SB.ToString的OOM异常.但是如果您的OOM异常是由于StringBuilder的内容添加自己,那么您应该对此进行处理.
public const int CHUNK_STRING_LENGTH = 30000;
while (SB.Length > CHUNK_STRING_LENGTH )
{
sw.Write(SB.ToString(0, CHUNK_STRING_LENGTH ));
SB.Remove(0, CHUNK_STRING_LENGTH );
}
sw.Write(SB);
Run Code Online (Sandbox Code Playgroud)
您必须记住,.NET 中的字符串以 16 位 unicode 存储在内存中。这意味着长度为 132370292 的字符串将需要 260MB 的 RAM。
此外,在执行时
string str = SB.ToString();
Run Code Online (Sandbox Code Playgroud)
您正在创建字符串的 COPY(另一个 260MB)。
请记住,每个进程都有自己的 RAM 限制,因此即使您还有一些空闲 RAM,也可能抛出 OutOfMemoryException。
| 归档时间: |
|
| 查看次数: |
23263 次 |
| 最近记录: |