【问题标题】:C# - What is the most efficient way to generate 10 character random alphanumeric string in?C# - 生成 10 个字符的随机字母数字字符串的最有效方法是什么?
【发布时间】:2011-09-23 19:53:40
【问题描述】:

在 c# 中生成 10 个字符的随机字母数字字符串的最有效方法是什么?

【问题讨论】:

  • 为什么/如何必须是最有效的?它必须是加密安全的吗?碰撞可以吗?
  • 那个,你想要多随机?用代码生成的随机数并不是真正随机的。
  • 您可以购买一张包含满是随机数文件的 CD,然后在需要时从文件中读取另一张。我开玩笑地说,但它确实存在。 westphal-electronic.com/z_cd_eng.htm
  • Henk 是对的——说“最有效率”是完全不可能的。如果您有性能要求,请说明您的要求。假设您需要能够在不到 5 微秒的时间内生成一个这样的字符串,或者每小时生成一万个这样的字符串,或者无论您的实际限制是什么。
  • 您接受了一个危险的错误答案。对于“随机”的任何定义,指南都保证随机。 Guid 保证是唯一的。 GUID 代表“全局唯一标识符”,而不是“随机标识符”。 不要将 guid 用作随机性来源,也不要将 guid 的片段用作唯一性来源。 Guid 不是随机的,除非您获取整个 guid,否则它们也不是唯一的。 (你不能坐半架飞机,并期望它是飞行的一半。)

标签: c# string random


【解决方案1】:

Guid 非常快

Guid.NewGuid().ToString("N").Substring(0, 10);

From MSDN

GUID 是一个 128 位整数(16 个字节),可以在需要唯一标识符的所有计算机和网络中使用。这样的标识符被复制的概率非常低。

对于十亿个请求,它可能不是唯一的,因为您只需要 10 个字符。但它会生成一个从 0 到 9 和 A 到 F 的字符串。


性能

测试使用

public static void Test(Action a)
{
    Stopwatch sw = new Stopwatch();
    sw.Start();

    for (var i = 0; i < 10000; ++i)
        a();

    sw.Stop();

    Console.WriteLine("ms: {0} ticks: {1}", sw.ElapsedMilliseconds, sw.ElapsedTicks);
}

指导方法

Test(() =>
{
    var xxx = Guid.NewGuid().ToString("N").Substring(0, 10);
});

// Result
// 6     ms
// 17273 ticks

字节法

Test(() =>
{
    var buffer = new byte[5];
    new Random().NextBytes(buffer);
    var x = string.Join("", buffer.Select(b => b.ToString("X2")));
});

// Result:
// 57     ms
// 165642 ticks

您可以在high speedhigh reliability 之间进行选择。

【讨论】:

  • GUID 不是随机数,如果您将其子串化,它甚至不一定是唯一的
  • 真的会比 Random.GetBytes 快吗?
  • @Henk:一般来说,随机数不一定是唯一的。
  • 但是说真的,GUID 的前 N ​​个位置是非常非随机的:blogs.msdn.com/b/oldnewthing/archive/2008/06/27/8659071.aspx。一个简单的 RNG(想到 System.Random)随时获胜,并且更易于使用
  • @sehe 该博文描述了一种不同于当前使用的 GUID 创建算法。当前的实现对于大多数位来说确实是随机的。当然,使用 GUID 作为 RNG 仍然是个坏主意。
【解决方案2】:
var buffer = new byte[5];
new Random().NextBytes(buffer);
Console.WriteLine(string.Join("", buffer.Select(b => b.ToString("X2"))));

【讨论】:

  • 或 new RNGCryptoServiceProvider.GetBytes(buffer);
  • 如果快速连续调用(即在几毫秒内调用两次),则会中断,因为您在每个请求上都创建了一个 Random 实例。
【解决方案3】:
var buffer = new byte[15];
new Random().NextBytes(buffer);
string rnd = Convert.ToBase64String (buffer).Substring (10);

我看到的唯一问题是它还使用了+/,所以你也必须用一些东西替换它们。

string rnd = Convert.ToBase64String (buffer)
   .Substring (10)
   .Replace ('/', '0')
   .Replace ('+', '1');

【讨论】:

    【解决方案4】:

    http://msdn.microsoft.com/en-us/library/system.io.path.getrandomfilename.aspx

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

    例如:

    ?Path.GetRandomFileName();
    "rlwi1uew.5ha"
    ?Path.GetRandomFileName();
    "gcwhcoiy.vxl"
    ?Path.GetRandomFileName();
    "2pzyljzf.k41"
    ?Path.GetRandomFileName();
    "kyjzcccf.d3c"
    

    【讨论】:

    • 你可以通过使用.Remove(8, 1)而不是Replace来提高性能
    • 鉴于我们从问题中不知道结果是否应该是加密安全的、防碰撞的(线程内或线程之间)等。这个答案是最安全的选择。
    猜你喜欢
    • 1970-01-01
    • 2012-12-29
    • 2020-12-01
    • 2010-09-08
    • 2021-04-05
    • 2011-08-18
    • 1970-01-01
    • 1970-01-01
    • 2018-04-07
    相关资源
    最近更新 更多