将 StringBuilder 的 OutOfMemoryException 的长度设置为 0
Putting length to 0 for OutOfMemoryException of StringBuilder
我有一个代码块,它获取一个文件并附加所需数据,如下所示:
var srBuilder = new StringBuilder();
using (var file = new StreamReader(document.FullSourcePath, Encoding.ASCII))
{
while (!file.EndOfStream)
{
var bytess = new char[numBytes];
file.ReadBlock(bytess , 0, bytess.Length);
srBuilder.Append(buff);
}
document.Document += srBuilder.ToString(); ////Exception occures here
}
但是当文件超过 200 MB 时,它会抛出 OutofMemoryException。
我想的是将字符串生成器的长度设为零,如下所示:
while (!file.EndOfStream)
{
srBuilder.Length = 0; //// Here
var bytess = new char[numBytes];
file.ReadBlock(bytess , 0, bytess.Length);
srBuilder.Append(buff);
}
这是最佳解决方案还是需要其他任何解决方案?
我不知道你为什么把它搞得那么复杂。您只需要一行:
document.Document += File.ReadAllText(document.FullSourcePath, Encoding.ASCII);
如果这抛出异常,那么是的,可能是您没有足够的内存。
您的最终目标是将一个 200 MB 的 ASCII 文件分配给 document.Document
成员变量,我假设它是字符串类型。
长话短说:你不能这样做,需要重新考虑你的方法。
无论如何,你的这个要求将需要 400 MB 的连续内存(给定的字符串是 char[]
个 UTF-16 字符数组,每个字符占 2 个字节),这几乎不可能获得在 32 位进程中,运行 时间抛出的 OutOfMemoryException
试图告诉您。
您将要找到的任何 "trick" 都会有其缺点。
- 分块读取文件无关紧要,因为最终结果是一样的:最终的字符串仍然需要 400 MB 的连续内存。
- 通过谷歌搜索 "C# StringBuilder OutOfMemoryException" 将
StringBuilder
的 Length
设置为 0,将使异常消失,但只会导致文件的最后一个块被分配至 document.Document
。可以肯定地说你也不想那样。
- 仅在 64 位机器上将项目更改为 运行 可能 是一个选项,但很可能不会(硬件和其他依赖项),并且是一个隐藏实际问题的肮脏解决方法,就像在被吹断的腿上贴创可贴:您忽略了致命的设计错误。有一天,有人要为您的应用程序提供一个 2 GB 的文件,而您又回到了原点。
您需要流文件,并逐行处理它。
foreach (string line in File.ReadLines(filename))
{
// process line
}
我有一个代码块,它获取一个文件并附加所需数据,如下所示:
var srBuilder = new StringBuilder();
using (var file = new StreamReader(document.FullSourcePath, Encoding.ASCII))
{
while (!file.EndOfStream)
{
var bytess = new char[numBytes];
file.ReadBlock(bytess , 0, bytess.Length);
srBuilder.Append(buff);
}
document.Document += srBuilder.ToString(); ////Exception occures here
}
但是当文件超过 200 MB 时,它会抛出 OutofMemoryException。
我想的是将字符串生成器的长度设为零,如下所示:
while (!file.EndOfStream)
{
srBuilder.Length = 0; //// Here
var bytess = new char[numBytes];
file.ReadBlock(bytess , 0, bytess.Length);
srBuilder.Append(buff);
}
这是最佳解决方案还是需要其他任何解决方案?
我不知道你为什么把它搞得那么复杂。您只需要一行:
document.Document += File.ReadAllText(document.FullSourcePath, Encoding.ASCII);
如果这抛出异常,那么是的,可能是您没有足够的内存。
您的最终目标是将一个 200 MB 的 ASCII 文件分配给 document.Document
成员变量,我假设它是字符串类型。
长话短说:你不能这样做,需要重新考虑你的方法。
无论如何,你的这个要求将需要 400 MB 的连续内存(给定的字符串是 char[]
个 UTF-16 字符数组,每个字符占 2 个字节),这几乎不可能获得在 32 位进程中,运行 时间抛出的 OutOfMemoryException
试图告诉您。
您将要找到的任何 "trick" 都会有其缺点。
- 分块读取文件无关紧要,因为最终结果是一样的:最终的字符串仍然需要 400 MB 的连续内存。
- 通过谷歌搜索 "C# StringBuilder OutOfMemoryException" 将
StringBuilder
的Length
设置为 0,将使异常消失,但只会导致文件的最后一个块被分配至document.Document
。可以肯定地说你也不想那样。 - 仅在 64 位机器上将项目更改为 运行 可能 是一个选项,但很可能不会(硬件和其他依赖项),并且是一个隐藏实际问题的肮脏解决方法,就像在被吹断的腿上贴创可贴:您忽略了致命的设计错误。有一天,有人要为您的应用程序提供一个 2 GB 的文件,而您又回到了原点。
您需要流文件,并逐行处理它。
foreach (string line in File.ReadLines(filename))
{
// process line
}