8자리의 랜덤 문자열을 작성하는 함수 rand8()

8자리의 랜덤 문자열을 작성하는 함수 rand8()

특정 자리수의 랜덤한 문자열을 20만건 작성해야 할 일이 생겨서 급하게 만들어봤다.
제한 조건으로는 절대로 겹치면 안된다는 것.
겹치지 않는 조건을 충족하기 위해 MySQL까지 동원해서 Unique성을 체크했다.

의외로 넷 상의 많은 공개 함수들이 엉터리였다.
또한 문자열 속에 포함되어야 하는 문자, 포함안될 문자를 설정하는 기능도 약했다.
우연히 구한 잘 된 함수 rand8()을 기록해 둔다.

정말 아쉽게도, 원래 출처였던 외국사이트의 공개 주소를 잃어버린 것 같아 죄송하다.
아래에 8자리의 랜덤 문자열을 작성하는 함수 rand8()에 대한 예제이다.
상단부 소스는 실패한 여타 함수들도 함께 있다.

<?
set_time_limit( 10000 );

function make_seed()
{
  list($usec, $sec) = explode(' ', microtime());
  return (float) (($sec + $usec ) * 100);
}

function VISION_TO_RANDOM
(
// autor Femi Hasani [www.vision.to]
$length=7, // string length
$uselower=1, // use lowercase letters
$useupper=1,  // use uppercase letters
$usespecial=1, // use special characters
$usenumbers=1, // use numbers
$prefix=''
)
{

    $key = $prefix;
// Seed random number generator
    // mt_srand((double)microtime() * rand(1000000, 9999999));
mt_srand( make_seed()*100 );

    $charset = "";
    if ($uselower == 1) $charset .= "abcdefghjkmnpqrstuvwxyz";
//    if ($useupper == 1) $charset .= "ABCDEFGHJKMNPQRSTUVWXYZ";
    if ($usenumbers == 1) $charset .= "23456789";
    // if ($usespecial == 1) $charset .= "~#$%^()_+-={}][";
    while ($length > 0) {
        $key .= $charset[rand(0, strlen($charset)-1)];
        $length--;
    }
    return $key;
}

function range2($start, $end, $length)
{
$str_array = range($start, $end);
srand((double) microtime() * 1000000);
$text = '';
for($i = 0; $i < $length; $i++)
{
$text .= $str_array[rand(0, count($str_array) - 1)];
}
return $text;
}

function createRandomPassword() {
    $chars = "abcdefghjkmnpqrstuvwxyz23456789";

    srand((double)microtime()*1000000);

    $i = 0;

    $pass = '' ;
    while ($i <= 7) {

        $num = rand() % 33;
        $tmp = substr($chars, $num, 1);
        $pass = $pass . $tmp;
        $i++;
    }

if ( strlen( $pass) == 8 )     return $pass;
else false;
}

// SUCCESS!
function rand8() {
      $len = 7;
      $base='abcdefghjkmnpqrstuvwxyz23456789';
      $max=strlen($base)-1;
      $activatecode='';
      mt_srand((double)microtime()*10000000); //// IMPORTANT!!!!! 10000000
      while (strlen($activatecode)<$len+1)
      $activatecode.=$base{mt_rand(0,$max)};

if ( strlen( $activatecode ) == 8 )     return $activatecode;
else false;
}

$conn = mysql_connect('localhost', 'www', 'www');
mysql_select_db( "test" );

while ( $ii < 10000000 ) {
// echo VISION_TO_RANDOM( 8 )."<br />";

// echo "insert into `serial8`(`sn`,`randvalue`) values ( NULL,'".VISION_TO_RANDOM( 8 )."');<br />";
// insert into `serial8`(`sn`,`randvalue`) values ( NULL,'8pawcvmh');

// $strSQL = "insert into `serial8`(`sn`,`randvalue`) values ( NULL,'".VISION_TO_RANDOM( 8 )."')";
$str = rand8();
if ( $str != false ) {
$strSQL = "insert into `serial8`(`sn`,`randvalue`) values ( NULL,'".$str."')";
}
// $strSQL = "insert into `serial8`(`sn`,`randvalue`) values ( NULL,'".range2( '2', 'z', 8 )."')";

$result = mysql_query( $strSQL );
if (!$result) {
// echo ('Invalid query: ' . mysql_error() . "<br />");
}
else
{
echo ('Inserted: ' . $strSQL . "<br />");
}

$ii++;
}

mysql_close( $conn );

/***
検証用SQL : randvalueフィールドはUnique条件
select count(1) from serial8 where length( randvalue )!=8
or randvalue like '%l%'
or randvalue like '%1%'
or randvalue like '%o%'
or randvalue like '%0%'
or randvalue like '%i%'
***/
?>

다음에 기회가 되면 이를 클래스화해서 공개하는 것도 좋을 것 같다.

우선 시간이 없어서 클래스화 했을 경우의 예제 소스를 기록해 둔다.

<?php
/**
* Uniqueな文字列をランダム生成するクラス
*
* PHP5.x用、PHP4.1.x系にも対応。
* このファイルはUTF-8フォーマット、TABの幅は4。
*
* @access  public
* @create  2008/11/28
* @version v0.1
**/

/**********************************
************  使用例  ************
**********************************

    ini_set('memory_limit', '64M');                    // 使用メモリの制限を伸ばす。(php.iniの設定が優先)
    set_time_limit( 3600 );                            // 実行時間を3600秒(1時間)まで伸ばす。
    require_once "class.RandomUnique.php";

    // 使用例 #1
    $objRU = new RandomUnique();                    // クラスのInstanceを生成。ランダム文字列のDefault桁数は8である。
    $str = $objRU->getString( 10000 );                // 1万件のUniqueなランダム文字列を返す。文字列の各結果は改行(\n)で区別。
    echo nl2br( $str );
    $arr = $objRU->getArray( 200000 );                // 20万件のUniqueなランダム文字列を配列(以下'文字配列')で返す。

    // 使用例 #2
    $objRU2 = new RandomUnique( "abxy123789", 6 );    // クラスのInstanceを生成する際に「文字リスト」と「桁」を設定。
    $arr2 = $objRU2->getArray( 10000000 );            // 1千万件のUniqueなランダム文字配列を返す。メモリ制限を越えるとエラーを配列で返す。

    // 使用例 #3
    $listChar = "abcdefghjkmnpqrstuvwxyz23456789";    // 「文字リスト」の準備。
    $objRU3 = new RandomUnique( $listChar );        // クラスのInstanceを生成する際に「文字リスト」を設定。Default桁数は8である。
    $objRU3->make( 30000 );                            // 3万件のUniqueなランダム文字配列で生成する。既存のラン

ダム文字値は廃棄される。
    $objRU3->save( "./output.txt" );                // ランダム文字列をファイル名output.txtで保存する。文字列の各結果は改行(\n)で区別。

    // 使用例 #4
    $objRU4 = new RandomUnique( null , 12 );        // ランダム文字列の桁数は12で設定。「文字リスト」がnullであればDefault値を使用。
    $objRU4->setChar( "abcdfgxyz23456789!#%*@" );    // ランダム文字列の生成のため使う「文字リスト」を設定。Default値は a~z, 0~9。
    $objRU4->setWidth( 10 );                        // ランダム文字列を(12桁から)10桁で変更。最大ランダム数は「文字

リスト」の長さ^10件。
    $objRU4->make( 40000 );                            // 4万件のUniqueなランダム文字配列で生成する。既存のラン

ダム文字値は廃棄される。
    $bUniq = $objRU4->isValid();                    // 配列で生成されたランダム文字列がUnique性と桁数を満たすか検証(結果はtrue /

false)。
    if ( !$bUniq ) var_dump($objRU4->getInvalid());    // ランダム文字列がUnique性を満たない場合、その原因である文字配列などを取得・表示。

**********************************/

class RandomUnique    {

}    // end of class RandomUnique

?>

code 필터에 의한

code 필터에 의한 들여쓰기가 엉망이네요.

댓글 쓰기

CAPTCHA
스팸방지를 위해 아래에 보이는 영문/숫자를 입력해 주세요.
Image CAPTCHA
Enter the characters shown in the image.