【问题标题】:Is this a good way to generate a string of random characters? [closed]这是生成随机字符串的好方法吗? [关闭]
【发布时间】:2010-11-01 21:01:42
【问题描述】:

我发现snippet 的代码生成一串随机字符。

但是有没有更优雅/更快/更可靠的方法来做到这一点?这似乎依赖于数字 26-91 是给定当前编码的有效字符这一事实。

/// <summary>
/// Generates a random string with the given length
/// </summary>
/// <param name="size">Size of the string</param>
/// <param name="lowerCase">If true, generate lowercase string</param>
/// <returns>Random string</returns>
private string RandomString(int size, bool lowerCase)
{
    StringBuilder builder = new StringBuilder();
    Random random = new Random();
    char ch;

    for(int i = 0; i < size; i++)
    {
        ch = Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65)));
        builder.Append(ch);
    }

    if(lowerCase)
        return builder.ToString().ToLower();

    return builder.ToString();
}

【问题讨论】:

  • 它不依赖于当前编码 - Convert.ToChar 总是 使用 Unicode,不管系统默认编码如何。不过,它在许多其他方面都很丑:)

标签: c# string random


【解决方案1】:

我更愿意将 Random 实例传递给方法 - 然后您可以多次重复使用同一个实例,如果您需要快速连续生成大量随机字符串,这一点很重要。但是,无论如何我也会对其进行一些修改:

public const string LowerCaseAlphabet = "abcdefghijklmnopqrstuvwyxz";
public const string UpperCaseAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

public static string GenerateUpperCaseString(int size, Random rng)
{
    return GenerateString(size, rng, UpperCaseAlphabet);
}

public static string GenerateLowerCaseString(int size, Random rng)
{
    return GenerateString(size, rng, LowerCaseAlphabet);
}

public static string GenerateString(int size, Random rng, string alphabet)
{
    char[] chars = new char[size];
    for (int i=0; i < size; i++)
    {
        chars[i] = alphabet[rng.Next(alphabet.Length)];
    }
    return new string(chars);
}
  • 知道最终长度后,无需使用 StringBuilder
  • 使用Random.NextDouble() 表示缺乏对 Random 类的了解。 (特别是Random.Next(int, int)
  • 在每次调用时创建一个新的 Random 可能会导致重复的字符串
  • 与仅强制转换相比,调用 Convert.ToInt32 和 Convert.ToChar 似乎很难看
  • 与选择小写字母开头相比,小写之后似乎毫无意义
  • 提供可供选择的字母表更加灵活(针对常见情况使用辅助方法)

【讨论】:

  • 是的,我认为这要好得多。只需创建一个包含您可接受的字符的字符串,然后从该字符串中随机选择字符,构建您自己的字符。我认为上面的例子可以简化,不需要将 rng 和字母参数传递给方法,但它给了你这个想法。
  • @Jeremy:传入 RNG 非常 很重要,除非您想要一个可能会创建重复字符串的方法。您可以保留一个静态的 Random 实例,但是您还需要担心锁定问题。
  • 乔恩一如既往的出色回答。结合其他需要考虑的事情。 (1) 随机到什么程度才足够随机?如果攻击者知道大小、字母表以及是否重复使用相同的 Random,则只要从您的版本中获得一个足够长度的字符串就足以推断出每个未来的输出将是什么。这种级别的随机性不适合加密使用、生成密码等。 (2) 这些随机字符串是否会显示给用户?我可以想到一些随机输出,用户可能会觉得这些输出令人反感或反感。可能想要过滤粗鲁的话。
  • 在这方面的一些额外想法(关于 VBScript,但问题几乎相同)在这里:blogs.msdn.com/gstemp/archive/2004/02/23/78434.aspx
  • 我想我被跟踪了 ;) 所有的优点。我可以想出一些有趣的方法来让它变得更难一些(比如保持一个“主”随机,并根据主生成的种子从中生成新的随机),但所有这些都可能有类似的问题。至于使用加密强度的 RNG……我们没有 one 具有不同实现的随机低音类,这不是很遗憾吗? (而不是 System.Random 和 System.Security.Cryptography.RandomNumberGenerator。)然后调用者可以决定他们想要的安全级别。就像 Java 的 Random/SecureRandom :)(续)
【解决方案2】:

如果我要这样做(我有,但在 Java 中,隐藏在某个地方),我会提供一个允许的字符数组,并使用 RNG 简单地选择字符的索引。这也可以让你禁止你不想生成的字符(如果你正在创建一个人工输入的许可证密钥,你不想生成可以相互混淆的字符;例如,0 和 O,或 1 和 l)。

编辑:是的,就像 Jon 所做的那样......

【讨论】:

    【解决方案3】:

    Path.GetRandomFileName()

    string randomName = Path.GetRandomFileName();
    randomName = randomName.Replace(".", string.Empty);
    
    // take substring...
    

    【讨论】:

      猜你喜欢
      • 2014-06-08
      • 2014-02-01
      • 2017-11-18
      • 1970-01-01
      • 1970-01-01
      • 2011-12-10
      • 2013-05-13
      • 2012-12-29
      • 1970-01-01
      相关资源
      最近更新 更多