首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从多个文件读取导致OutOfMemory异常

从多个文件读取导致OutOfMemory异常
EN

Stack Overflow用户
提问于 2017-01-20 23:26:01
回答 2查看 296关注 0票数 0

我有一个从10个文件中读取文本的代码,每个文件的大小约为80MB。然而,我无法成功做到这一点,因为(取决于我尝试的方式)它在第3-7次迭代中失败了。注释掉的行是我尝试阅读它的方法,每一行都失败了。

代码语言:javascript
复制
var lines = new List<string>();
var text = string.Empty;
for (int i = 0; i < 10; i++)
{
    try
    {
        //lines.AddRange(File.ReadAllLines(dirPath + string.Format(@"commands{0}.txt", i)));
        //lines.Add(File.ReadAllText(dirPath + string.Format(@"commands{0}.txt", i)));
        //lines.Add(text);

        var bytes = File.ReadAllBytes(dirPath + string.Format(@"commands{0}.txt", i));
        text += Environment.NewLine + System.Text.Encoding.UTF8.GetString(bytes);
    }
    catch (Exception e)
    {
        //OutOfMemory exception
    }
}

我做错了什么?到底是什么被封顶了?应用程序允许的MB,字符串的长度,列表中的项数?等等?

EN

回答 2

Stack Overflow用户

发布于 2017-01-20 23:36:54

text是一个有限制的string对象。What is the maximum possible length of a .NET string?

您可以使用StringBuilder,它可以通过附加到它上面而超出它的限制。https://msdn.microsoft.com/en-us/library/system.text.stringbuilder.maxcapacity(v=vs.110).aspx

首先添加using System.Text

代码语言:javascript
复制
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++)
{
    var bytes = File.ReadAllBytes(dirPath + string.Format(@"commands{0}.txt", i));
    sb.Append(Environment.NewLine + System.Text.Encoding.UTF8.GetString(bytes));
}
票数 1
EN

Stack Overflow用户

发布于 2017-01-20 23:46:21

问题出在string text上。string是不可变的。这意味着当您在创建后更改string时,将创建新的string对象。

执行此操作:

代码语言:javascript
复制
text += Environment.NewLine + System.Text.Encoding.UTF8.GetString(bytes);

你在每次迭代中创建对象(甚至不止一个对象-- Environment.NewLine + System.Text.Encoding.UTF8.GetString(bytes);创建一个对象,然后你再创建text +=创建一个对象)。

假设您已经读取了第一个文件,然后通过第二个文件中的文本附加此string -内存中将存储包含来自文件的文本的旧string和包含来自两个文件的文本的新string。旧的string被存储,但不需要。

有很多内存是不需要的,但垃圾回收还没有完成(这就是为什么有时你会在第三次迭代中得到异常,有时在第七次迭代中-如果发生GC,你会更进一步)。

要避免这种情况,请考虑使用byte阵列或StringBuilder,而不是string

关于 List<string>**:**的

在内部,list保存一个数组,当没有连续(连续)的内存区域可以分配给这个数组时,你也会得到OutOfMemoryException

您可以尝试使用LinkedList<string>

使用StringBuilder

代码语言:javascript
复制
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10; i++)
{
    try
    {
        var bytes = File.ReadAllBytes(dirPath + string.Format(@"commands{0}.txt", i));

        sb.Append(Environment.NewLine);
        sb.Append(System.Text.Encoding.UTF8.GetString(bytes));    

        //avoid sb.Append(Environment.NewLine + System.Text.Encoding.UTF8.GetString(bytes)) 
        //because you still create unnecessary object doing concatenation (+)    
    }
    catch (Exception e)
    {
        //OutOfMemory exception
    }
}

//you can cast "sb" to "string"
string res = sb.ToString();

但您应该考虑创建另一个解决方案。在内存中保留800MB并不是最好的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41767074

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档