missingcat92
missingcat92

Reputation: 1076

How to convert redis bitmap(binary string) to binary number with leading zero?

I am using redis bitmap to record user action in a year, if user login in the first day in the year, I'll set the first bit of key to 1. the redis value like this:

key: user.18.action(18 is user id)
value: (bitmap) 000100000000000000000000...(about 365 bit long)

but when I was trying to get the value, GET user.18.action returns "\x10".

In PHP, how do I convert these strings to the 000100000000000000000000... thing?

Actually, I use the code below to implement it, but is this all right? and is there a better resolution?

$bitmap = $this->redis->get('user.18.action');
$binstrlen = strlen($bitmap);
$hex = bin2hex($bitmap);
$str = str_baseconvert($hex, 16, 2);
var_dump(str_pad($str, $binstrlen * 8, '0', STR_PAD_LEFT));

function str_baseconvert($str, $frombase=10, $tobase=36) { 
    $str = trim($str); 
    if (intval($frombase) != 10) { 
        $len = strlen($str); 
        $q = 0; 
        for ($i=0; $i<$len; $i++) { 
            $r = base_convert($str[$i], $frombase, 10); 
            $q = bcadd(bcmul($q, $frombase), $r); 
        } 
    } 
    else $q = $str; 

    if (intval($tobase) != 10) { 
        $s = ''; 
        while (bccomp($q, '0', 0) > 0) { 
            $r = intval(bcmod($q, $tobase)); 
            $s = base_convert($r, 10, $tobase) . $s; 
            $q = bcdiv($q, $tobase, 0); 
        } 
    } 
    else $s = $q; 

    return $s; 
}

Upvotes: 3

Views: 1520

Answers (2)

user2311194
user2311194

Reputation: 111

The bitmap_human func is on my head

 /**
 * @param \Redis $redis
 * @param $key
 * @param $or_login_user
 * @return array
 */
protected function parseUserList(\Redis &$redis, $key)
{
    $bitmap = $this->bitmap_human($redis->get($key));
    $bitmap_length = strlen($bitmap);
    $bitSet = [];

    for ($i = 0; $i < $bitmap_length; $i++) {
        if (1 == $bitmap[$i]) {
            $bitSet[] = $i;
        }
    }

    if(empty($bitSet)){
        return [];
    }

    $login_user = M('user')->cache(600)->field('id,phone,nickname')->where(['id'=>['in',$bitSet]])->select();

    return $login_user;
}

Upvotes: 0

missingcat92
missingcat92

Reputation: 1076

function bitmap_human($bitmap){
    $bytes = unpack('C*', $bitmap);
    $bin = join(array_map(function($byte){
        return sprintf("%08b", $byte);
    }, $bytes));
    return $bin;
}

I figured this out, works all right.

Upvotes: 5

Related Questions