如何以二进制安全的方式从多字节PHP字符串变量中获取单个字节?

时间:2013-08-01 11:32:59

标签: php utf-8 byte bytearray multibyte

让我们说(为了简单起见)我有一个多字节,UTF-8编码的字符串变量,包含3个字母(由4个字节组成):

$original = 'Fön';

由于它是UTF-8,字节的十六进制值是(不包括BOM):

46 C3 B6 6E

由于$original变量是用户定义的,我需要处理两件事:

  1. 获取字符串中使用的确切字节数(不是UTF-8字符)和
  2. 访问每个字节(不是UTF-8字符)的方法。
  3. 我倾向于使用strlen()来处理“1.”,并使用这样的简单$original访问`$original[$byteposition]变量的字节:

    <?php
    header('Content-Type: text/html; charset=UTF-8');
    
    $original = 'Fön';
    $totalbytes = strlen($original);
    for($byteposition = 0; $byteposition < $totalbytes; $byteposition++)
    {
        $currentbyte = $original[$byteposition];
    
        /*
            Doesn't work since var_dump shows 3 bytes.
        */
        var_dump($currentbyte);
    
        /*
            Fails too since "ord" only works on ASCII chars.
            It returns "46 F6 6E"
        */
        printf("%02X", ord($currentbyte));
        echo('<br>');
    }
    
    exit();
    ?>
    

    这证明了我最初的想法是行不通的:

    1. var_dump显示3个字节
    2. printf也失败,因为“ord”仅适用于ASCII字符
    3. 如何以二进制安全的方式从多字节PHP字符串变量中获取单个字节?

      我正在寻找的是将UTF-8字符串转换为字节数组的二进制安全方法。

2 个答案:

答案 0 :(得分:4)

你可以通过解压缩utf8_ecoded字符串获得一个bytearray $ a:

$a = utf8_encode('Fön');
$b = unpack('C*', $a); 
var_dump($b);

使用格式C *表示“unsigned char”

<强>参考

答案 1 :(得分:0)

我实际上是为这个问题写了自己的课。
我试图在PHP中制作javascript new TextEncoder("utf-8").encode(...)
这就是我想出的: 它使用PHP
ord()函数用于获取字节
chr()函数来构建utf8消息回来

class Uint8Array{
    public $val = array();
    public $length = 0;
    function from($string, $mode = "utf8"){
      if($mode == "utf8"){
      $arr = [];
      foreach (str_split($string) as $chr) {
        $arr[] = ord($chr);
      }
      $this->val = $arr;
      $this->length = count($arr);
      return $arr;
      }
      elseif($mode == "hex"){
      $arr = [];
      for($i=0;$i<strlen($string);$i++){
        if($i%2 == 0)
          $arr[] = hexdec($string[$i].$string[$i+1]);
      }
      $this->val = $arr;
      $this->length = count($arr);
      return $arr;
      }
    }
    function toString($enc = "utf8"){
      if($enc == "utf8"){
          $str = "";
        foreach($this->val as $byte){
          $str .= chr($byte);
        }
        return $str;
      }
      elseif($enc == "hex"){
        $str = "";
        foreach($this->val as $byte){
          $str .= str_pad(dechex($byte),2,"0",STR_PAD_LEFT);
        }
        return $str;
      }
    }
  }

像这样使用它:

创建实例:

$handle = new Uint8Array;
使用->from(string, encoding)进行

输入,如下所示: 1)utf8 2)十六进制字节(无空格)

$handle->from("Fön","utf8");
//or with hex bytes
$handle->from("46c3b66e","hex");

->toString(encoding) hex / utf8输出:

$to_utf8 = $handle->toString("utf8");
//Fön
$to_hex = $handle->toString("hex");
//46c3b66e

字节数组本身可以在->val中找到,如您在此处看到的那样:

$bytearray = $handle->val;
//[70, 195, 182, 110]
$arrayleng = $handle->length;
//4

仅此而已,请随意使用!

您可以在此处了解有关二手功能的更多信息:
chr() ord()