1

この質問が以前に尋ねられたことは知っていますが、読んだ回答ではうまくいかないようです。私はCSVファイルを持っています〜1.2GB 、32ビットのようにプロセスを実行している場合、outOfMemoryExceptionを取得します。64ビットプロセスとして実行すると機能しますが、それでもメモリに3.4GBかかります。 customData クラスに大量のデータを格納していますが、まだ 3.4GB の RAM が残っていますか? ファイルを読み取るときに何か問題がありますか? dict は、その列に応じて、何かを保存するプロパティへのマッピングを持っている辞書です。正しい方法で読んでいますか?

StreamReader reader = new StreamReader(File.OpenRead(path));
while(!reader.EndOfStream)  {
            String line = reader.ReadLine();
            String[] values = line.Split(';');
            CustomData data = new CustomData();
            string value;
            for (int i = 0; i < values.Length; i++) {
                dict.TryGetValue(i, out value);
                Type targetType = data.GetType();
                PropertyInfo prop = targetType.GetProperty(value);
                if(values[i]==null)
                {
                    prop.SetValue(data, "NULL",null);
                }
                else
                {
                    prop.SetValue(data, values[i], null);
                }

            }
            dataList.Add(data);
        }
4

2 に答える 2

3

ストリーム リーダーの使用法に問題はないようです。メモリ内の行を読み取った後、それを忘れてしまいます。

ただし、C# では、文字列はメモリ内で UTF-16 としてエンコードされるため、平均して文字はメモリ内で 2 バイトを消費します。

CSV に変換先の空のフィールドが多数含まれている場合は、空の"NULL"フィールドごとに最大 7 バイトを追加します。

全体として、基本的にファイルのすべてのデータをメモリに格納するため、メモリ内のファイルのサイズのほぼ 3 倍が必要になることは驚くことではありません。

実際の解決策は、データを N 行のチャンクで解析し、処理して、メモリから解放することです。

注: CSV パーサーの使用を検討してください。CSV にはカンマやセミコロンだけではありません。フィールドの 1 つにセミコロン、改行、引用符が含まれている場合はどうなりますか?

編集

実際には、各文字列はメモリ内で最大 20+(N/2)*4 バイトを使用しますC# の詳細を参照してください

于 2012-07-13T08:04:24.470 に答える
3

ここでいくつかのポイントがあります。

  • コメントで指摘されているように、x86 での .NET はプロセスごとに 1.5G バイトしか消費できないため、32 ビットでの最大メモリを考慮してください。

  • StreamReader 自体にはオーバーヘッドがあります。ファイル全体をメモリにキャッシュするかどうかはわかりません(誰かが明確にできるでしょうか?)。もしそうなら、チャンクでファイルを読んで処理することはより良い解決策かもしれません

  • CustomData クラスにはいくつのフィールドがあり、いくつのインスタンスが作成されますか? x86 では参照ごとに 32 ビット、x64 では参照ごとに 64 ビットが必要になることに注意してください。したがって、System.Object 型の 10 個のフィールドを持つ CustomData クラスがある場合、データを格納する前の各 CustomData クラスには 88 バイトが必要です。

  • 最後に dataList.Add 。一般的なリストに追加していると思いますか?その場合、List は 2 倍のアルゴリズムを使用してサイズを変更することに注意してください。リストに 1GByte があり、さらに 1 バイトのサイズが必要な場合、2GByte 配列が作成され、サイズ変更時に 1GByte が 2GByte 配列にコピーされます。したがって、突然、1GByte + 1 バイトを実際に操作するには 3GBytes が必要になります。別の代替手段は、事前にサイズ設定された配列を使用することです

于 2012-07-13T08:10:14.430 に答える