目录
一、进制转换函数 dechex, hexdec, decbin, bindec, base_convert
二、编码解码函数 bin2hex, hex2bin, pack, 和 unpack
PHP字符串,从PHP 5.2.1版本 引入binary即二进制字符串。二进制binary字符串,是一种基于字节的字符串,在显示时可能存在不可见字符。通常情况下,我们使用的是ASCII字符组成的字符串,而以b开头的字符串,通常含有不可见字符。
一、进制转换函数 dechex, hexdec, decbin, bindec, base_convert
1、转换为十进制时结果类型为整数,而转换为二进制和十六进制时结果为字符串
2、进制转换的对象,仅为字符串形式的整数。针对字符串时,可以理解为ASCII编码值。
3、base_convert在二进制,八进制,和十六进制之间转换时,可以同时转换一串数字,但转换后的进制数会省略前导零。
4、字节编码序数和二进制字符的转换函数有,ord() 和 chr()。其中,ASCII码字符也不全是可见字符:
a、0~31及127(共33个)是控制字符或通信专用字符(其余为可显示字符),如控制符:LF(换行)、CR(回车)、FF(换页)、DEL(删除)、BS(退格)、BEL(响铃)等;通信专用字符:SOH(文头)、EOT(文尾)、ACK(确认)等;ASCII值为8、9、10 和13 分别转换为退格、制表、换行和回车字符。它们并没有特定的图形显示,但会依不同的应用程序,而对文本显示有不同的影响。
b、32~126(共95个)是字符(32是空格),其中48~57为0到9十个阿拉伯数字。
c、65~90为26个大写英文字母,97~122号为26个小写英文字母,其余为一些标点符号、运算符号等。
例子:
<?php
/**
* PHP进制转换函数
* 十进制 88 = 十六进制 58 = 二进制 1011000
*/
$dec = 88;
$hex = dechex($dec); //'58'
$bin = decbin($dec); //'1011000'
/* notes: 如果将$dec初始化为字符串'88'得到的结果不变 */
$hex = '58';
$dec = hexbin($hex); //88
$bin = '1011000';
$dec = bindec($bin); //88
/* notes: 转换为十进制时,类型为整数,而不是字符串 */
$dec = 8.8;
$hex = dechex($dec); //'8'
$bin = decbin($dec); //'1000'
/* notes: 如果有小数,小数部分会被忽略 */
$hex_str = '1F1F';
$bin_str = base_convert($hex_str, 16, 2); //"1111100011111", 省略前"0001111100011111"
$ch = "X";
$ord = ord($ch); //'88'
$chr = chr($ord); //'X'
二、编码解码函数 bin2hex, hex2bin, pack, 和 unpack
1、bin2hex函数,将字符串在内存中的字节码 =>转换为=> 十六进制字符串,主要用于查看字符串在内存中的字节码,结果为十六进制数的字符串形式。
2、hex2bin函数,将十六进制的内存字节码 =>写入到=> 内存,并返回字节字符串(可能为不可见字符,超出ASCII编码范围)(可能未定义,已定义0-127)。
3、unpack ( string $format
, string $data
[, int $offset
= 0 ] ) : array
$format 为显示结果的类型格式,而$data是内存编码数据,即将内存编码进行解码;
将内存编码值,按照指定类型格式,转换为字符串形式的结果值。
返回内存编码值的指定类型数据,(若为ASCII码字符(c),即返回ASCII值;若为十六进制数(H),则返回内存编码值的十六进制等价值)
unpack('H*', $str) 和 bin2hex($str) 等价,都是查看ASCII码字符串内存编码值,结果为指定类型的数据。
4、pack ( string $format
[, mixed $args
[, mixed $...
]] ) : string
$format为$args的类型格式, 而结果为内存编码数据,即对数据进行编码。
pack('H*', $str) 和 hex2bin($str) 等价,都是操纵内存编码,结果为该内存编码值的ASCII码字符串。
5、PHP默认对内存编码数据,以ASCII码字符串的形式进行显示。
注意:unpack解码的结果是数组。
<?php
/*
* PHP内存编码与解码
*/
$c = 'X';
//查看字符'X'的ASCII码的十进制形式
var_dump(hexdec(bin2hex($c))); //88
var_dump(hexdec(unpack('H*', $c)[1])); //88
$code = 88;
//查看ASCII码对应的字符
var_dump(hex2bin(dechex($code))); //'X'
var_dump(pack('H*', dechex($code))); //'X'
/* 字符'X',ASCII码值88,十六进制58 */
//解码
var_dump(ord('X')); //88, 求字符'X"的ASCII值
var_dump(unpack('C*', 'X')[1]);//88, 类似ord('X')
var_dump(bin2hex('X')); //'58', 求字符'X'的十六进制内存编码
var_dump(unpack('H*', 'X')[1]);//'58', 类似ord('X')
//编码
var_dump(chr(88)); //'X', 求ASCII码值对应的字符
var_dump(pack('C*', '88')); //'X', 类似chr(88)
var_dump(hex2bin('58')); //'X', 求内存编码为0x58的ASCII字符
var_dump(pack('H*', '58'));//'X', 求内存编码为0x58的ASCII字符
6、PHP默认字符串为ASCII编码,常说的ASCII码值默认为十进制。
三、字符串类型详解
PHP 中的 string 的实现方式是一个由字节组成的数组再加上一个整数指明缓冲区长度。并无如何将字节转换成字符的信息,由程序员来决定。字符串由什么值来组成并无限制;特别的,其值为 0("NUL bytes")的字节可以处于字符串任何位置(不过有几个函数,在本手册中被称为非"二进制安全"的,也许会把 NUL 字节之后的数据全都忽略)。
字符串类型的此特性解释了为什么 PHP 中没有单独的"byte"类型 - 已经用字符串来代替了。返回非文本值的函数 - 例如从网络套接字读取的任意数据 - 仍会返回字符串。
由于 PHP 并不特别指明字符串的编码,那字符串到底是怎样编码的呢?例如字符串 "á" 到底是等于 "\xE1"(ISO-8859-1),"\xC3\xA1"(UTF-8,C form),"\x61\xCC\x81"(UTF-8,D form)还是任何其它可能的表达呢?答案是字符串会被按照该脚本文件相同的编码方式来编码。因此如果一个脚本的编码是 ISO-8859-1,则其中的字符串也会被编码为 ISO-8859-1,以此类推。不过这并不适用于激活了 Zend Multibyte 时;此时脚本可以是以任何方式编码的(明确指定或被自动检测)然后被转换为某种内部编码,然后字符串将被用此方式编码。注意脚本的编码有一些约束(如果激活了 Zend Multibyte 则是其内部编码)- 这意味着此编码应该是 ASCII 的兼容超集,例如 UTF-8 或 ISO-8859-1。不过要注意,依赖状态的编码其中相同的字节值可以用于首字母和非首字母而转换状态,这可能会造成问题。
当然了,要做到有用,操作文本的函数必须假定字符串是如何编码的。不幸的是,PHP 关于此的函数有很多变种:
- 某些函数假定字符串是以单字节编码的,但并不需要将字节解释为特定的字符。例如 substr(),strpos(),strlen() 和 strcmp()。理解这些函数的另一种方法是它们作用于内存缓冲区,即按照字节和字节下标操作。
- 某些函数被传递入了字符串的编码方式,也可能会假定默认无此信息。例如 htmlentities() 和 mbstring 扩展中的大部分函数。
- 其它函数使用了当前区域(见 setlocale()),但是逐字节操作。例如 strcasecmp(),strtoupper() 和 ucfirst()。这意味着这些函数只能用于单字节编码,而且编码要与区域匹配。例如 strtoupper("á") 在区域设定正确并且 á 是单字节编码时会返回 "á"。如果是用 UTF-8 编码则不会返回正确结果,其结果根据当前区域有可能返回损坏的值。
- 最后一些函数会假定字符串是使用某特定编码的,通常是 UTF-8。intl 扩展和 PCRE(上例中仅在使用了 u 修饰符时)扩展中的大部分函数都是这样。尽管这是由于其特殊用途,utf8_decode() 会假定 UTF-8 编码而 utf8_encode() 会假定 ISO-8859-1 编码。
最后,要书写能够正确使用 Unicode 的程序依赖于很小心地避免那些可能会损坏数据的函数。要使用来自于 intl 和 mbstring 扩展的函数。不过使用能处理 Unicode 编码的函数只是个开始。不管用何种语言提供的函数,最基本的还是了解 Unicode 规格。例如一个程序如果假定只有大写和小写,那可是大错特错。