我有一个从10个文件中读取文本的代码,每个文件的大小约为80MB。然而,我无法成功做到这一点,因为(取决于我尝试的方式)它在第3-7次迭代中失败了。注释掉的行是我尝试阅读它的方法,每一行都失败了。
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,字符串的长度,列表中的项数?等等?
发布于 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。
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));
}发布于 2017-01-20 23:46:21
问题出在string text上。string是不可变的。这意味着当您在创建后更改string时,将创建新的string对象。
执行此操作:
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
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并不是最好的。
https://stackoverflow.com/questions/41767074
复制相似问题