3

1M のランダムな (出現する) 一意の英数字キーを生成し、それらをデータベースに保存したいと考えています。各キーの長さは 8 文字で、サブセット "abcdefghijk n pqrstuvxyz and 0-9" のみが使用されます。

l、m、o、w の文字は省略されています。各キーは製品の非常に小さなスペースに印刷されるため、印刷スペースが限られているため、「m と w」は省略されています。m と w を削除すると、文字サイズが 2pt 増加し、可読性が向上しました。l と o は、現在の印刷サイズでは 1、i、および 0 と混同しやすいため削除されました。文字 1、i、および 0 は常に正しく読み取られ、l と o は多くの間違いがあったことをテストしました。m と w と同じ理由で、大文字は除外されました。

では、なぜシーケンスではないのでしょうか? いくつかの理由: キーは後で登録できるため、誰かがシーケンスの次のキーを推測して、他の誰かのキーを登録したくありません。外観: 数千個のキーしか出荷していないことを顧客や競合他社に知られる必要はありません。

キーを生成し、各キーの一意性を確保してデータベースに保存する実用的な方法はありますか? ありがとう!

4

5 に答える 5

6

編集: @CodeInChaos は問題を指摘しました:System.Randomあまり安全ではなく、シーケンスはそれほど困難なく再現できました。Randomここで安全なジェネレーターに置き換えました:

var possibilities = "abcdefghijknpqrstuvxyz0123456789".ToCharArray();
int goal = 1000000;
int codeLength = 8;
var codes = new HashSet<string>();
var random = new RNGCryptoServiceProvider();
while (codes.Count < goal)
{
    var newCode = new char[codeLength];
    for (int i = 0; i < codeLength; i++)
        newCode[i] = possibilities[random.Next(possibilities.Length)];
    codes.Add(new string(newCode));
}
// now write codes to database

static class Extensions
{
    public static byte Next(this RNGCryptoServiceProvider provider, byte maximum)
    {
        var b = new byte[1];
        while (true)
        {
            provider.GetBytes(b);
            if (b[0] < maximum)
                return b[0];
        }
    }
}

(次の方法はそれほど高速ではありませんが、目的には十分かもしれません)

于 2012-06-15T15:17:28.303 に答える
1

最近では 100 万は大したことではありませんが、おそらく 1 台のマシンでそれをかなり迅速に行うことができます。結局のところ、それは1回限りの操作です。

  1. ハッシュテーブル (またはハッシュセット) を取得する
  2. ランダムなキーを生成し、カウントが 100 万になるまでキーとして (またはセットの場合は直接) 入れます。
  3. それらをデータベースに書き込む

私の簡単で汚いテストコードは次のようになりました:

function new-key {-join'abcdefghijknpqrstuvxyz0123456789'[(0..7|%{random 32})]}
$keys = @{}
for(){$keys[(new-key)]=1}

しかし、PowerShell は遅いので、ここでは C++ または C# が非常にうまく機能すると思います。

于 2012-06-15T15:15:54.977 に答える
1

私は一度同様の問題に遭遇しました..私がしたことは、一意のシーケンスYYYY/MM/DD/HH/MM/SS/millis/nanoを作成し、そのハッシュコードを取得することです。その後、ハッシュをキーとして使用します。あなたのクライアントと競合他社は、次の価値を推測することができなくなります。完全な証拠ではないかもしれませんが、私の場合はそれで十分でした!

于 2012-06-15T15:20:44.037 に答える
1

キーを生成し、各キーの一意性を確保してデータベースに保存する実用的な方法はありますか?

これは単一の操作であるため、次のように簡単に実行できます。

1) 単一のキーを生成する
2) 生成されたキーがデータベースに存在しないことを確認します。
3) 存在する場合は、新しいキーを生成します。
3b) 存在しない場合は、データベースに書き込みます。 4) ステップ 1 に戻ります。

もちろん、他の選択肢もあります。最終的には、キーを生成し、それがデータベースに存在しないことを確認します。

理論的には、(処理能力を節約するために) 1,000 万個のキーを生成してファイルに書き込むことができます。キーが生成されたら、それぞれを見て、データベースに既に存在するかどうかを確認します。 これを 48 時間以内に実行するツールをプログラムできる可能性があります。

于 2012-06-15T15:12:18.843 に答える
0

実際にランダム文字列を取得するには、次のようなコードを使用できます。

Random rand = new Random(new DateTime().Millisecond);
String[] possibilities = {"a","b","c","d","e","f","g","h","i","j","k",
    "l","n","p","q","r","s","t","u","v","x","y","z","0","1","2","3","4",
    "5","6","7","8","9"};
for (int i = 0; i < 1000000; ++i)
{
    System.Text.StringBuilder sb = new System.Text.StringBuilder();
    for (int j = 0; j < 8; ++j)
    {
        sb.Append(possibilities[rand.Next(possibilities.Length)]);
    }
    if (!databaseContains(sb.ToString()))
        databaseAdd(sb.ToString());
    else
        --i;
}
于 2012-06-15T15:21:49.293 に答える