0

現在、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();
    }
4

3 に答える 3

2

手始めに、プロファイラーに投資することを強くお勧めします。これは、コードの実行に時間がかかっている理由や大量のメモリを使用している理由を判断する正しい方法です。Premium または Ultimate を使用している場合は、Visual Studio 2010 に組み込まれているものを含め、多くのプロファイラーがあります。

他の人については、Googleまたはこれらの投稿を参照してください。

優れた .NET プロファイラーとは?

最高の .NET メモリとパフォーマンス プロファイラー?

第 2 に、アプリが 1ギガのメモリを超えてはならないなどと考えるべきではありません。C# アプリケーション (実際には、すべての .NET アプリケーション) はガベージ コレクトされます。十分な RAM を備えたコンピューターを使用している場合、メモリ プレッシャーがなければ GC を実行する必要はありません。そうでない場合、アプリケーションは簡単に 1 ギガのメモリを使い果たしてしまいます。これは、プロセスが 32 ビット アドレス空間のメモリ制限を受けない 64 ビット環境に特に当てはまります。

于 2012-04-19T06:41:04.310 に答える
0

まず比較の 2 つのバリアント:

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);
}
于 2012-04-19T06:41:54.367 に答える
0

1) 静的メソッドFile.ReadAllBytesを知っていますか? コードの最初の 15 行を節約できます。

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();

したがって、ファイルの各バイトに対して、バイト自体とそのインデックスを含むオブジェクトを作成します。わお。ファイルが 15 MB の場合、それは 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)
  ));
}

これは数倍速くなるはずです。

それでも、パフォーマンスを向上させるために、ファイルを読み取るときに、すべてのバイトをメモリに保持せずに、データベースにチャンクを挿入することがあります。

于 2012-04-19T07:09:39.707 に答える