目前,当我读取一个15Mb的文件时,我的应用程序已经过了一大堆内存。 请注意,在主代码的末尾,我将数据库中插入的数据与文件中的原始数组进行比较。欢迎任何建议。
主要代码:
TestEntities entities = new TestEntities();
using (FileStream fileStream = new FileStream(fileName + ".exe", FileMode.Open, FileAccess.Read))
{
byte[] bytes = new byte[fileStream.Length];
int numBytesToRead = (int) fileStream.Length;
int numBytesRead = 0;
while (numBytesToRead > 0)
{
int n = fileStream.Read(bytes, numBytesRead, numBytesToRead);
if (n == 0)
break;
numBytesRead += n;
numBytesToRead -= n;
}
var query = bytes.Select((x, i) => new {Index = i, Value = x})
.GroupBy(x => x.Index/100)
.Select(x => x.Select(v => v.Value).ToList())
.ToList();
foreach (List<byte> list in query)
{
Binary binary = new Binary();
binary.Name = fileName + ".exe";
binary.Value = list.ToArray();
entities.AddToBinaries(binary);
}
entities.SaveChanges();
List<Binary> fileString = entities.Binaries.Where(b => b.Name == fileName + ".exe").ToList();
Byte[] final = ExtractArray(fileString);
if (Compare(bytes, final))
{
/// Some notification that was ok
}
}
比较方法:
public bool Compare(Byte[] array1,Byte[] array2)
{
bool isEqual = false;
if (array1.Count() == array2.Count())
{
for (int i = 0; i < array1.Count(); i++)
{
isEqual = array1[i] == array2[i];
if (!isEqual)
{
break;
}
}
}
return isEqual;
}
ExtractArray方法:
public Byte[] ExtractArray(List<Binary> binaries )
{
List<Byte> finalArray = new List<Byte>();
foreach (Binary binary in binaries)
{
foreach (byte b in binary.Value)
{
finalArray.Add(b);
}
}
return finalArray.ToArray();
}
答案 0 :(得分:2)
对于初学者,我强烈建议您投资一个分析器。这是确定代码运行时间如此之长或者使用大量内存的正确方法。有许多个人资料,包括one built into Visual Studio 2010,如果你有Premium或Ultimate。
请参阅google或其他人的帖子:
What Are Some Good .NET Profilers?
和
Best .NET memory and performance profiler?
其次,您可能不应该假设您的应用不应该重温内存。 C#应用程序(实际上,所有.NET应用程序)都是垃圾回收。如果我的计算机有足够的RAM,那么没有理由在没有内存压力的情况下运行GC,如果没有,应用程序就可以轻松地耗尽内存。对于64位环境尤其如此,其中进程不受32位地址空间的内存限制。
答案 1 :(得分:0)
最初是comapre的两个变体:
bool arraysAreEqual = Enumerable.SequenceEqual(array1, array2);
或者这个
public bool Compare(Byte[] array1, Byte[] array2)
{
if (array1.Length != array2.Length)
return false;
for (int i = 0; i < array1.Length; i++)
{
if (array1[i] != array2[i])
return false;
}
return true;
}
关于提取试试这个:
foreach (Binary binary in binaries)
{
finalArray.AddRange(binary.Value);
}
答案 2 :(得分:0)
1)你知道静态方法File.ReadAllBytes吗?可以保存前十五行代码。
2)我讨厌Linq ......难以理解,很难理解究竟发生了什么。
var query = bytes.Select((x, i) => new {Index = i, Value = x})
.GroupBy(x => x.Index/100)
.Select(x => x.Select(v => v.Value).ToList())
.ToList();
因此,对于文件的每个字节,您将创建一个包含字节本身及其索引的对象。哇。如果你的文件是15mb,那就是15 728 640个对象。假设这个对象需要64个字节,即960mb的内存空间。
顺便问一下,你想做什么?修改强>
var bytes = File.ReadAllBytes(filename);
var chunkCount = (int)Math.Ceilling(bytes.Length / 100.0);
var chunks = new List<ArraySegment<byte>>(chunkCount);
for(int i = 0; i < chunkCount; i++) {
chunks.Add(new ArraySegment(
bytes,
i * 100,
Math.Min(100, bytes.Length - i * 100)
));
}
这应该快几倍。
但是,为了获得更好的性能,您可以在读取文件时在数据库中插入块,而不将所有这些字节保留在内存中。