1. 程式人生 > >如何快速生成 UUID GUID

如何快速生成 UUID GUID

問題的由來:

      我們經常會遇到需要一些特殊的值來指定一些特殊的變數,而且這個值要絕對的唯一。在windows下被稱作GUID,其實GUID是微軟對Distributed coumputing environment (DCE) universally unique identifier 的實現,而在Linux下則稱作UUID。

不論它叫什麼名字,表達的意願都是一樣的,以下用GUID泛指這一概念。它實際上是一個包含128位的bit組。那我們到底如何獲取它呢?

先來看看windows平臺下如何實現:

通用的GUID的結構如下

typedef struct _GUID {
  DWORD Data1

;
  WORD Data2;
  WORD Data3;
  BYTE Data4[8];
} GUID;

舉一個例子:

假設一個GUID的格式是這樣的 6B29FC40-CA47-1067-B31D-00DD010662DA

其中Data1 是32位,可以看做8個四位十六進位制數,對應於上面的6B29FC40

其中Data2 是16位,可以看做4個四位十六進位制數,對應於上面的CA47

其中Data3 是16位,可以看做4個四位十六進位制數,對應於上面的1067

其中Data4 比較特殊,是8個位元組也就可以看做16個四位十六進位制數

      取其Data4[0],Data4[1]來組成4個四位十六進位制數,對應於上面的B31D

      取其Data4[2],Data4[3]來組成4個四位十六進位制數,對應於上面的00DD

      取其Data4[4],Data4[5]來組成4個四位十六進位制數,對應於上面的0106

      取其Data4[6],Data4[7]來組成4個四位十六進位制數,對應於上面的62DA

*注意:四位十六進位制數對應一個GUID字元。

在Windows下提供了一個函式可以生成一個GUID。需要使用的標頭檔案 "objbase.h",需要連結的庫ole32.lib。

HRESULT CoCreateGuid(GUID * pguid);

在Linux下首先需要下載到相應的庫檔案和標頭檔案

如果是Debian使用者可以方便的通過apt命令來獲取相關資源。

     apt-get install uuid-dev

安裝完成後會發現

       在/usr/include/ 下有一個uuid資料夾,其中則包含了uuid.h標頭檔案。

       在/usr/lib/ 下有幾個libuuid*的連結庫檔案,包括靜態和動態連結庫。

開啟uuid.h你會發現有一個uuid_generate(uuid_t out) 的函式宣告。我們可以通過呼叫這個函式來生成UUID。

uuid_generate(reinterpret_cast<unsigned char *>(&guid));

生成GUID是不是很簡單!是的,因為生成的演算法不用我們去實現,我們是站在前人的肩膀所以我們要感謝他們。

下面給出一個WINDOWS和LINUX下通用的程式。

// uuid_test.cpp

#include <string>
#include <stdio.h>
#include <iostream>

#include "uuid_test.hpp"

#ifdef WIN32
#include <objbase.h>
#else
#include <uuid/uuid.h>
#endif

using namespace std;

namespace ChinuxTeam
{
GUID CreateGuid()
{
    GUID guid;
#ifdef WIN32
    CoCreateGuid(&guid);
#else
    uuid_generate(reinterpret_cast<unsigned char *>(&guid));
#endif
    return guid;
}

std::string GuidToString(const GUID &guid)
{
    char buf[64] = {0};
#ifdef __GNUC__
    snprintf(
#else // MSVC
    _snprintf_s(
#endif
                buf,
                sizeof(buf),
                 "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
                guid.Data1, guid.Data2, guid.Data3,
                guid.Data4[0], guid.Data4[1],
                guid.Data4[2], guid.Data4[3],
                guid.Data4[4], guid.Data4[5],
                guid.Data4[6], guid.Data4[7]);
        return std::string(buf);
}
}

對應的標頭檔案

// uuid_test.hpp"

#include <string>
#include <stdio.h>
#include <iostream>

typedef struct _GUID
{
    unsigned long Data1;
    unsigned short Data2;
    unsigned short Data3;
    unsigned char Data4[8];
} GUID, UUID;

namespace ChinuxTeam

{

GUID CreateGuid();

std::string GuidToString(const GUID &guid);

}// namespace ChinuxTeam

最後一個 GuidToString()稍微解釋一下,作用就是把GUID以固定的格式輸出到標準string字串中,

根據編譯器的不同調用分別呼叫了不同的字串列印函式。

另外附一個簡單的測試函式

#include <string>
#include <stdio.h>
#include <iostream>

#ifdef WIN32
#include "objbase.h"
#else

typedef struct _GUID
{
    unsigned long Data1;
    unsigned short Data2;
    unsigned short Data3;
    unsigned char Data4[8];
} GUID, UUID;

#endif

namespace ChinuxTeam{

GUID CreateGuid();

std::string GuidToString(const GUID &guid);

}

 執行後會生成一個GUID並列印到標準輸出的控制檯上。