C# - 取得隨機字串的快速方法

用程式產生隨機字串是身為一個Programmer必須具備的基本技能,不管是用在測試, 破解, 加密...等各種用途上。通常聽到這個產生隨機字串的需求,大部分的Programmer都會想到最正規的方法實作,分別產生出對應數量的字元,再將字元串接成字串。至於要怎麼產生出隨機字元各有解法,在這篇文章中,限量要來說明幾種取得隨機字串的快速程式寫法。

前面說到正規的做法是產生出對應數量的字元,再將字元串接成字串。產生隨機字元的方法,有人利用ASCII Code編號範圍方式,取出隨機編號數字,再將編號數字轉換為字元,例如65 => A, 55 => 7, 126 => ~;另外有其他人的作法在一開始給定一個包含許多字元的陣列,然後再隨機取出陣列中的字元,以下為字元陣列的隨機字串程式碼:


public static string GetRandomString4(int length)
{
    var str = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    var next = new Random();
    var builder = new StringBuilder();
    for(var i = 0; i < 5; i++)
    {
        builder.Append(str[next.Next(0, str.Length)]);
    }
    return builder.ToString();
}


程式碼中,隨機字串中的字元只會在str裡取出。

上面提到的方法都是比較屬於正統的做法,但其實有一些邪魔歪道的方法可以一兩行就取得隨機字串,以下為三種快速方法:


使用System.IO.Path

由標題就知道是使用System.IO.Path類別所提供的方法,那要用哪個方法呢?其實是使用GetRandomFileName()方法。使用.Net Reflector進去看GetRandomFileName()的實作方式,可以看到底層使用方式也是正規的隨機字串方法。這裡要注意的是因為產生出的字串會有"."這個字元,所以要將"."用空白字元取代掉,畢竟這個方法是產生出隨機檔案名稱。下面為將GetRandomFileName()修改為產生隨機字串的Code:


public static string GetRandomStringByFileName(int length)
{
    var str = Path.GetRandomFileName().Replace(".", "");
    return str.Substring(0, length);
}

使用GetRandomFileName()有幾缺點,就是這最多只會有長度11的字串,字元只包含數字與英文字母小寫(Alphanumeric Charactors)。


使用System.Web.Security.Membership

接著這種方法是使用System.Web.Security.Membership所提供的GeneratePassword()方法
MSDN定義為public static string GeneratePassword(int length, int numberOfNonAlphanumericCharactors),numberOfNonAlphanumericCharactors為Non Alphanumeric Charactors的數量(Non Alphanumeric Charactors是泛指非A~Z與0~9的字元,例如~!@#$...等)。下面為將GeneratePassword()修改為產生隨機字串的Code:


public static string GetRandomStringByPassword(int length, int nonAlphaCount)
{
    var str = Membership.GeneratePassword(length, nonAlphaCount);
    return str;
}

與GetRandomFileName()不同的是使用GeneratePassword()的隨機字串長度可以自己調整,且字元不受限於Alphanumeric Charactors;但缺點是要額外引入System.Web的DLL,且當設定nonAlphaCount為0時似乎沒有作用。



使用Guid

Guid是Global Unique Identifier(全域唯一識別項)的簡稱,是一個16Byte的結構,將Guid轉換為字串會得到類似下列格式的結果:"936DA01F-9ABD-4d9d-80C7-02AF85C822A8",因此,可以應用這個特性來產生隨機字串,類似GetRandomFileName()的方式,我們可以取得Guid的字串並將"-"字元取代掉即可,下面為Guild修改為產生隨機字串的Code:


public static string GetRandomStringByGuid(int length)
{
    var str = Guid.NewGuid().ToString().Replace("-", "");
    return str.Substring(0, length);
}

使用Guid產生隨機字串與GetRandomFileName()的方式有一樣的問題,就是字元只包含數字與英文字母小寫(Alphanumeric Charactors),但比GetRandomFileName()好的方式在於它長度較GetRandomFileName()長。


看完了這幾種產生隨機字串的快速寫法,是不是發現到這些寫法所呼叫的API的主要目的都不是產生隨機字串,但我們卻可以利用它來達到目的,節省了許多程式碼,這告訴我們寫程式不一定要一直侷限在正規的作法,有時可以讓思考方向轉向,或許會有更好的解法,記得之前看"微軟英雄"這部電影中有出現來自畢卡索的一句名言:"好的藝術家擅複製,偉大的藝術家則擅偷取",程式設計師也是一樣的,雖然不一定要要成為偉大的程式設計師,但至少要當一個好的程式設計師。



參考來源:
C# Random String
MSDN - Membership.GeneratePassword Method

留言