4

文字列からパックされた16進数を抽出しようとしています。私のアプリケーションは、ヘッダーとそれに続く2バイトの16進数を含む文字列を送信するサーバーと通信しています。この文字列には何千もの数字が含まれています。

私がやりたいのは、2バイトの圧縮された数値をそれぞれ抽出し、それを計算に使用できる数値に変換することです。

例:string = "info:\x00\x00\x11\x11\x22\x22"3つの数値0x0000(10進数の0)、0x1111(10進数の4369)、0x2222(10進数の8738)を生成します

私には実用的な解決策がありますが(以下を参照)、サーバーが送信する数千の数値を処理しようとすると、機能が遅すぎます。私のアプローチをスピードアップするためのいくつかの推奨事項を提供してください。

//Works but is too slow!
//$string has the data from the server
$arrayIndex = 0;
for($index = [start of data]; $index < strlen($string); $index+=2){
    $value = getNum($string, $index, $index+1);
    $array[$arrayIndex++] = $value;
}
function getNum($string, $start, $end){
    //get the substring we're interested in transforming
    $builder = substr($string, $start, $end-$start+1);  

    //convert into hex string
    $array = unpack("H*data", $builder);
    $answer = $array["data"];

    //return the value as a number
    return hexdec($answer);
}

また、単一のunpackコマンドで数値を抽出しようとしましたが、機能していません(使用するフォーマット文字列を理解するのに問題があります)

//Not working alternate method
//discard the header (in this case 18 bytes) and put the rest of the
//number values I'm interested in into an array
$unpacked = unpack("c18char/H2*data", $value);
for($i = 0; $i < $size; $i+=1){
    $data = $unpacked["data".$i];
    $array[$i] = $data;
}
4

3 に答える 3

2
$array = array();
$len = strlen($string);
for($index = [start of data];          $index < $len;               $index+=2){
    $d = unpack("H*data", substr($string, $index, 2));
    $array[] = hexdec($d["data"]);
}

私がした唯一の重要なことは、strlenの値をキャッシュし、関数呼び出しを減らすことでした。

あなたもこれを試すことができます

foreach (str_split(substr($string, [start of data]), 2) as $chunk) {
    $d = unpack("H*data", $chunk);
    $array[] = hexdec($d["data"]);
}
于 2012-06-29T18:30:52.923 に答える
1

私が提案できることの1つは、値ではなく、参照を介して数千の16進数を含む文字列を渡すことです。たとえば、3kの数値がある場合、文字列は長い12k文字であり、3kの関数呼び出しが複数あると、スタックに不必要に割り当てられたメモリが最大36M(charごとに1バイト使用される場合、utf8の場合は約72M)になります。

$arrayIndex = 0;
for($index = [start of data]; $index < strlen($string); $index+=2){
    $value = getNum($string, $index, $index+1);
    $array[$arrayIndex++] = $value;
}
 //pass by reference rather than value
function getNum(&$string, $start, $end){
    //get the substring we're interested in transforming
    //$builder = substr($string, $start, $end-$start+1);  
    //not sure if substr takes reference or value, so implementing this way, just in case it's by value
      $builder = $string[$start] . $string[$start + 1] ;
    //convert into hex string
    $array = unpack("H*data", $builder);
    $answer = $array["data"];

    //return the value as a number
    return hexdec($answer);
}

これがどれだけ高速化するかはわかりませんが(確かにメモリ割り当て)、一見の価値があります。

于 2012-06-29T18:18:28.567 に答える
0

次のようなものを試してみませんか:

$string = "info:\x00\x00\x11\x11\x22\x22";

$ret = array();
preg_match_all('#\\x(\d{2})#', $string, $items);
if(isset($items[1]) && count($items[1])>0)
{
     for($i=0;$i<count($items[1]);$i+=2)
     {
            if(isset($items[1][$i]) && isset($items[1][$i+1]))
            {
                    $ret[] = '0x' . $items[1][$i] . $items[1][$i+1];
                    unset($items[1][$i]);
                    unset($items[1][$i+1]);
            }
     }
}
于 2012-06-29T18:19:39.783 に答える