为了简单起见,我们假设我有一个多字节、UTF-8编码的字符串变量,包含3个字母(由4个字节组成):
$original = 'Fön';
由于是UTF-8,字节的十六进制值为(不包括BOM):
46 C3 B6 6E
由于$original
变量是用户定义的,我需要处理两件事:
- 获取字符串中使用的确切字节数(不是UTF-8字符),然后
- 一种访问每个单独字节(而不是UTF-8字符)的方法
我倾向于使用strlen()
来处理"1.",并使用一个简单的`$original[$byteposition]
来访问$original
变量的字节,如下所示:
<?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();
?>
这证明了我最初的想法不起作用:
- var_dump显示3个字节
- printf也失败了,因为"ord"只适用于ASCII字符
如何以二进制安全的方式从多字节PHP字符串变量中获取单个字节?
我正在寻找一种二进制安全的方法,将UTF-8字符串转换为字节数组。
您可以通过拆包utf8_encoded字符串$a:来获得字节数组
$a = utf8_encode('Fön');
$b = unpack('C*', $a);
var_dump($b);
使用格式C*表示"无符号字符"
参考
- php中的字符串到字节数组
- http://www.php.net/manual/en/function.unpack.php
- http://www.php.net/manual/en/function.pack.php
实际上我为这个问题编写了自己的类
我试图用PHP制作javascript new TextEncoder("utf-8").encode(...)
这就是我的想法:它使用PHP
用于获取字节的ord()
函数
以及用于构建utf8消息返回的CCD_ 7功能
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()