耗尽内存构建大量字符串

时间:2011-11-02 10:41:59

标签: c#

我有一个程序将byte []转换为十六进制字符串:

byte[] bytes = File.ReadAllBytes(infile);

try
{
    StringBuilder sb = new StringBuilder(BitConverter.ToString(bytes)); // <--exception 
    hexfield.Text = sb.ToString();  
}

catch(Exception e) 
{
    MessageBox.Show(e.ToString()); 
} 

这适用于大多数情况。但是,当我使用一个巨大的文件,例如一个103 MB的.flv视频文件时,它会耗尽内存,它会引发异常:

System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.
at System.String.CtorCharArrayStartLength(Char[] value, Int32 startIndex, Int32 length)
at System.BitConverter.ToString(Byte[] value, Int32 startIndex, Int32 length)
at System.BitConverter.ToString(Byte[] value)
 at shex.shexx.hexfield_Dragrop(Object sender, DragEventArgs e)** 

4 个答案:

答案 0 :(得分:1)

我会使用BinaryReader来读取部分文件并将每个部分添加到stringbuilder中,而不是一次读取整个文件并将其转换为字符串。

查看this documentation

答案 1 :(得分:1)

那么就不要喂BitConverter.ToString这样大的数组。比如每次1 MB就可以了。

例如,使用BinaryReader

答案 2 :(得分:0)

您是否考虑过流媒体?这取决于你想要对该字符串做什么,如果你发送它,这是最有可能的情况,当你可以发送它的小部分,这是流。一些协议实现也允许构建一个chuck并刷新它,所以我建议这样做。

在您的情况下,您只能读取文件的某些部分,然后进行分析。 Checkout BinaryReader,FileStream类和流媒体

答案 3 :(得分:0)

BitConverter.ToString方法首先创建一个char数组,然后从中创建一个字符串,因此在内存中需要两次字符串空间。

您可以将数据转换为较小的块,并创建具有初始大小的StringBuilder,以便它具有所需的所有空间。这样大字符串在内存中只存在一次:

StringBuilder b = new StringBuilder(bytes.Length * 3 - 1);
int pos = 0;
while (pos < bytes.Length - 1000) {
  b.Append(BitConverter.ToString(bytes, pos, 1000)).Append('-');
  pos += 1000;
}
b.Append(BitConverter.ToString(bytes, pos));
hexfield.Text = b.ToString();

然而,请注意关于这么大的字符串的用处的评论。最好的解决方案实际上可能是根本不创建整个字符串。