代码之家  ›  专栏  ›  技术社区  ›  Kamran Khan

12位唯一ID-代码可靠性

  •  0
  • Kamran Khan  · 技术社区  · 16 年前

    我想要一个在一天(24小时)内保持唯一的数字。下面是我想出的代码;我想知道它的谬误/可能的风险;'我相信“这保证了一天内至少有一个12位数的唯一数字。

    逻辑是获取查询性能计数器结果的前四个字节的当前日期/时间(hhmmsmmm)和concat。

    __forceinline bool GetUniqueID(char caUID[MAX_STRING_LENGTH])
    {
        //Logic: Add HHMMSSmmm with mid 3 bytes of performance counter.
        //Guarantees that in a single milli second band (0 to 999) the three bytes 
        //of performance counter would always be unique.
        //1. Get system time, and use
        bool bStatus = false;
        try
        {
    
            SYSTEMTIME localtime;
            GetLocalTime(&localtime);//Get local time, so that we may pull out HHMMSSmmm
    
            LARGE_INTEGER li;
            char cNT[MAX_STRING_LENGTH];//new time.
            memset(cNT, '\0', sizeof(cNT));
            try
            {
                //Try to get the performance counter,
                //if one is provided by the OEM.
    
                QueryPerformanceCounter(&li);//This function retrieves the current value of the 
                                             //high-resolution performance counter if one is provided by the OEM
                                             //We use the first four bytes only of it.
                sprintf(cNT, "%u", li.QuadPart);
            }
            catch(...)
            {
                //Not provided by OEM.
                //Lets go with the GetTickCounts();
                //ddHHMMSS + 4 bytes of dwTicks
                sprintf(cNT,"%04d", GetTickCount());
            }
    
    
            //Get the first four bytes.
            int iSkipTo     = 0;//This is incase we'd decide to pull out next four bytes, rather than first four bytes.
            int iGetChars   = 4;//Number of chars to get.
            char *pSub = (char*) malloc(iGetChars+1);//Clear memory
            strncpy(pSub, cNT + iSkipTo, iGetChars);//Get string
            pSub[iGetChars] = '\0'; //Mark end.
    
            //Prepare unique id
            sprintf(caUID, "%02d%02d%02d%3d%s", 
                                        localtime.wHour, 
                                        localtime.wMinute, 
                                        localtime.wSecond, 
                                        localtime.wMilliseconds, 
                                        pSub); //First four characters concat.
    
            bStatus = true;
        }
        catch(...)
        {
            //Couldnt prepare. There was some problem.
            bStatus = false;
        }
    
        return bStatus;
    }
    

    以下是我得到的输出:

    唯一:[125907 462224] 唯一:[125907 462227] 唯一:[125907 462228] 唯一:[125907 462230] 唯一:[125907 462233] 唯一:[125907 462235] 唯一:[12590746237] 唯一:[125907 462238] 唯一:[125907 462241] 唯一:[125907 462245] 唯一:[12590746246] 唯一:[125907 462248] 唯一:[12590746249] 唯一:[125907 462252] 唯一:[125907 462254] 唯一:[125907 462255] 唯一:[125907 462256] 唯一:[125907 462257] 唯一:[125907 462258] 唯一:[125907 622261] 唯一:[125907 622263] 唯一:[125907 622264] 唯一:[125907 622268] 唯一:[125907 622269] 唯一:[125907 622270] 唯一:[125907 622271] 唯一:[125907 622273] 唯一:[125907 622275] 唯一:[125907 622278] 唯一:[125907 622281] 唯一:[125907 622282] 唯一:[125907 622283] 唯一:[125907 622285] 唯一:[125907 622286] 唯一:[125907 622288] 唯一:[125907 622290] 唯一:[125907 622291] 唯一:[125907 622293] 唯一:[125907 622297] 唯一:[125907 622298] 唯一:[125907 622299] 唯一:[125907 622300] 唯一:[125907 622302] 唯一:[125907 622305] 唯一:[125907 782308] 唯一:[125907 782310] 唯一:[125907 782312] 唯一:[125907 782314] 唯一:[125907 782316] 唯一:[125907 782318] 毫秒改变,125 唯一:[1259071402495] 唯一:[1259071402497] 唯一:[1259071402498] 唯一:[1259071402499] 唯一:[1259071402502] 唯一:[1259071402503] 唯一:[1259071402504]

    现在我考虑将生成的ID保存在一个列表中,并将新生成的ID与列表中现有的ID进行比较。如果它已经存在于列表中,那么我当然可以跳过这个数字并生成另一个,但显然这个逻辑会失败。

    非常感谢您的意见/建议/更新等。

    6 回复  |  直到 15 年前
        1
  •  1
  •   Aaron Digulla    16 年前

    static int counter = 0;
    static Time lastTime;
    
    String getNextId() {
        Time now = System.getTime();
        if (lastTime == now)
            counter ++;
        else
            counter = 0;
        return now+counter;
    }
    

    这将保证即使我调用该方法的次数超过 getTime() 变化。

        2
  •  1
  •   lc.    16 年前

    出于好奇,您不使用guid有什么原因吗?

    或者,既然您正在考虑将生成的ID保存在一个列表中进行比较,为什么不能创建一个生成器?由于您建议存储是一个选项,如果您存储上次使用的数字并在每次使用时递增它。。。如果您愿意,您甚至可以存储日期并每天重置计数器。

        3
  •  0
  •   Michael    16 年前

    我在快速循环中遇到过一些问题,它们没有改变,尽管这是常识,它们应该改变(你无法控制操作系统,所以你不能假设时间每x毫秒改变一次,等等)

    格式为TTTTOOO,其中T为时间数字,o为4位偏移量。

        4
  •  0
  •   Kamran Khan    16 年前

    __forceinline bool GetUniqueIDEx(char caUID[MAX_STRING_LENGTH])
    {
        //Logic: Add HHMMSSmmm with 3 bytes counter.
        //Guarantees a unique number for a calendar date, 
        //that in a single milli second band (0 to 999) the three bytes 
        //of counter would always be unique.
        //1. Get system time, and use
    
        bool bStatus = false;
        try
        {
            GetLocalTime(&localtime);//Get local time, so that we may pull out HHMMSSmmm
    
            char cNT[MAX_STRING_LENGTH];//new time.
            memset(cNT, '\0', sizeof(cNT));
            if(m_nCounter> MAX_COUNTER_LIMIT)
            {
                m_nCounter= 0;
            }
    
            sprintf(cNT, "%03d", ++m_nCounter);
    
            //Prepare unique id
            sprintf(caUID, "%02d%02d%02d%03d%s", 
                                                localtime.wHour, 
                                                localtime.wMinute, 
                                                localtime.wSecond, 
                                                localtime.wMilliseconds, 
                                                cNT); 
    
            bStatus = true;
        }
        catch(...)
        {
            //Couldnt prepare. There was some problem.
            bStatus = false;
        }
    
        return bStatus;
    }
    
        5
  •  0
  •   jmucchiello    16 年前

    sprintf(idstr, "%05d%07d", secs_since_midnight, counter);
    

    当然,当你真的想把计数器塞进几个可打印的字符(和一年中的某一天,而不是月/日,等等)时,我也坚信使用base-36(通过itoa)

        6
  •  0
  •   Manikanthan Velayutham    15 年前

    我不确定您的流程是否可以牺牲微小的性能问题并保持逻辑简单。

    如果您在两次呼叫之间将进程休眠1毫秒,我们可以保证HHMMSMM格式本身的唯一号码。通过这种方式,您可以消除连接部分,也可以消除为了双重检查唯一性而必须维护的列表。