进制和编码的关系
进制是数字上的关系
- 我们日常使用的是10进制,因为我们有10个手指,这是习惯和发展使然。
- 计算机的基础是2进制,因为电路只有通电、不通电两种状态,用0、1表示。一个数字成为一个
位
随着计算机的发展,需要表示的符号越来越多,从一开始的2位代表一字节,到后面的8位代表一字节至今。
- 其他的还有8进制、16进制等等。 进制之间的转换工具
编码是符号的映射表示关系
字符串在线转2进制 工具 由于计算机是MG发明的,一开始的映射表是ASSIC码,用一个字节(8位)表示一个符号或者字母 比如小写字母a对应的是97 相应的2进制为01100001
8个位的2进制最大值是11111111
所以当它不够用之后,就出现了双字节字符集
,比如GBK,Unicode等 再之后为了优化传输 出现了UTF-8,UTF-16等规范标准。 见这张我自己画的小图吧~
php中的进制转换
在php中 内置了挺多的进制转换函数
- bindec() — 二进制转换为十进制
- decbin() — 十进制转换为二进制
- dechex() — 十进制转换为十六进制
- decoct() — 十进制转换为八进制
- hexdec() — 十六进制转换为十进制
- octdec() — 八进制转换为十进制
- base_convert()– 在任意进制之间转换数字
php中的2进制输出
在我们日常写程序的时候,我们面向的是编码
,而不是进制。 代码会经过编译器或者解释器变成机器指令,再转换为2进制。 常见的文件编码格式现在有:GBK
、UTF-8
在机器传输过程中只能2进制,不管是GBK编码还是UTF-8编码,都可能是这样子的数据01010001111010101001111
,至于怎么解析,就看机器通信之间的规定了 从关系图中可以得知:UTF-8是Unicdoe的实现,Unicode又兼容了assic码的定义。
所以当我们在UTF-8文件的php程序输出小写字母a
的时候,经过解析会转换得到97这个10进制的数。 如果要输出16进制或者2进制的数据,其实我们可以先转换为10进制的数字
,然后使用chr()函数,转换得到assic码,输出。
assic码在传输过程会变成2进制,与我们一开始设定的16进制或者2进制数据其实是一样的,进制是可以互相转换的。
简单代码
连接tcp服务器 并且发送不同进制的数据,从服务器测观察拿到的结果
<?php //使用 stream_socket_client 打开 tcp 连接 $fp = stream_socket_client("tcp://127.0.0.1:6000"); //向句柄中写入数据 延迟一下 本地tcp服务器 可能监听慢 sleep(1); // 发送16进制数据 16进制转10进制str 然后chr 转assic码 传输 // $hexStr = "A3 B5 C1"; // $hexStr = str_replace(' ', '', $hexStr); // $send = ''; // for ($i=0; $i < strlen($hexStr); $i = $i+2) { // $decStr = base_convert($hexStr[$i].$hexStr[$i+1], 16, 10); // $send .= chr($decStr); // } // 第二种方式 chr可以直接传数字(10进制) 0x (16进制) 还有八进制 // fwrite($fp, chr(0xA3).chr(0xb5).chr(0xC1)); // sleep(5); // 发送2进制数据 2进制转10进制str 然后chr 转assic码 传输 // $binStr = '00011111'; // $decStr = base_convert($binStr, 2,10); // $send = chr($decStr); // fwrite($fp, $send); // sleep(5); $ret = ""; // //循环遍历获取句柄中的数据,其中 feof() 判断文件指针是否指到文件末尾 // while (!feof($fp)){ // stream_set_timeout($fp, 2); // $ret .= fgets($fp, 128); // } //关闭句柄 fclose($fp); echo $ret;