2

.NET 4.5 を使用して C# でアプリケーションを作成しています。私のアプリケーションは、ハードウェア デバイスによって消費されるバイナリ ファイルを読み書きします。ファイルは正確に 5,000,000 バイトで、100,000 個の 50 バイトの「ブロック」で構成されています。各 50 バイト ブロックには、ASCII エンコードされた文字列が含まれます (空の文字列の可能性もあります)。オフセット (インデックス * 50 バイト、および次の 50 バイトの読み取り/書き込み) を決定するだけで任意の文字列にアクセスできるように、ファイル レイアウトはデバイスによって必要とされます。

私の WinForms アプリケーションは、次のことができる必要があります。

  • ファイルから 100,000 個の文字列をすべて読み込み、UI (リストボックス) に表示します。
  • 文字列の追加、編集、または削除
  • バイナリファイルを適切な形式で書き直します

警告:

  1. バイナリ ファイル内のかなりの量のデータは、最初はユーザーに表示したくない空の文字列ですが、ファイルを適切に書き直すことができるようにデータ構造に含める必要があります。
  2. 新しい文字列を追加する前に、それを許可する空き領域 (つまり、空の 50 バイト ブロックが少なくとも 1 つ) があることを確認する必要があります。そうでない場合、ユーザーは既存の文字列を「削除」して、新しい文字列を追加するためのスペースを作る必要があります。
  3. 文字列の追加、変更、および削除は、舞台裏では同じ操作です。追加は 50 バイトの null データを 50 バイトの文字列データに変更するだけで、削除はその逆を表します。
  4. 空の文字列を除いて、重複する文字列は保存されるべきではないため、データ構造を繰り返し処理して、文字列を追加する前、または文字列を編集して既存の文字列と一致させないようにする必要があります。

したがって、ファイルのすべてのデータを保持するデータ構造が必要になり、辞書、リスト、または配列のいずれかを決定するのに苦労しています。上記の注意事項を考えると、データ構造を UI に直接バインドすることは実行可能な解決策ではないと思います。したがって、ある種の疑似バインディングを実装するには、そのデータ構造とリストボックスの間に多くのコードが必要になると思います。その場合、どのデータ構造 (辞書、リスト、配列、その他) が機能的な観点から最も有用であり、最高の妥協案を提供します: このサイズのデータ​​セット (最大 50 ASCII 文字の 100,000 文字列) の速度各)?

4

4 に答える 4

3

パフォーマンスが重要な場合、それを把握する最善の方法はテストすることです。重要なことを 3 つの方法すべてで実行する簡単なアプリを作成し、それをすべて 10,000 回実行するループにラップして、どちらが速いかを確認します。

于 2012-12-11T22:42:30.150 に答える
3

データにインデックスを付けるキーがないため、ここではディクショナリは必要ないようです。
リストはアイテムの追加/削除に適していますが、これも明らかに必要ではありません。
だから私は文字列配列に行きます

編集:複数の空の文字列が存在することを再考すると、空の文字列と塗りつぶされた文字列の比率が低くない場合、可能な最適化を提案できます。
塗りつぶされた文字列のみを含む辞書に対して、整数の配列をマップとして使用できます

警告: テストが必要です

int[] keys = new int[100];  // Just 100 to test the idea
Dictionary<int, string> data = new Dictionary<int, string>();

AddItem(keys, 32, data, "Position 32 34567890123456789012345678901234567890");
AddItem(keys, 40, data, "Position 40 34567890123456789012345678901234567890");
AddItem(keys, 10, data, "Position 10 34567890123456789012345678901234567890");
AddItem(keys, 25, data, "Position 25 34567890123456789012345678901234567890");
AddItem(keys, 99, data, "Position 99 34567890123456789012345678901234567890");
AddItem(keys, 0, data, "Postion 00 234567890123456789012345678901234567890");
AddItem(keys, 18, data, "Position 18 34567890123456789012345678901234567890");

foreach(int x in keys)
{
    if(x == 0)
        Console.WriteLine("Empty string");
    else
        Console.WriteLine(data[x]);
}

void AddItem(int[] keys, int keyPos, Dictionary<int, string> data, string message)
{
    int count = data.Count;
    data.Add(count, message);
    keys[keyPos] = count;
}
void RemoveItem(int[] keys, int keyPos, Dictionary<int, string> data)
{
    int x = keys[keyPos];
    data.Remove(x);
    keys[keyPos] = 0;
}
void UpdateItem(int[] keys, int keyPos, Dictionary<int, string> data, string message)
{
    int x = keys[keyPos];
    data[x] = message;
}
于 2012-12-11T22:43:23.737 に答える
1

10万件のエントリーがあっても、パフォーマンスについてあまり心配する必要はないと思います。(編集:つまり、I / Oまたはデータの変更に関するパフォーマンス。GUIバインディングに問題がある可能性があります)

ビジネスロジックとGUIバインディングに変更を加えるのが最も簡単になる最も簡単な方法でプログラムします。おそらく、この実装の詳細を隠すGUIの標準のパブリックインターフェイスでList(または何でも)を単にラップする独自のクラスを作成することを検討してください。Array

GUIが実行され、すべてのI / Oが正常に実行されたら(理想的には、単体テストの優れたスイートがいくつかあります)、ベンチマーク/プロファイリングを開始して、ボトルネックがどこにあるかを見つけることができます。

編集:要件を考慮すると、このカスタム/ラップされたデータ構造が理想的かもしれません。データの特定の側面を事前に知ることができます。たとえば、ロード/読み取り時に、新しい文字列にスペースが使用可能かどうかを確認できるため、ユーザーがさらに追加しようとすると、可能かどうかがすでにわかります。HashSet使用済みの一意の文字列を維持できるため、重複する文字列をO(1)で検索できます。

于 2012-12-11T22:53:43.997 に答える