很多时候,数据并不是用文本的方式保存的,这就需要将二进制数据读取出来,还原成我们需要的格式。PHP在二进制处理方面也提供了强大的支持。

任务

下面以读取并分析一个PNG图像的文件头为例,讲解如何使用PHP读取和分析二进制文件。

涉及函数

PNG格式简介

为了完成任务,下面简单介绍一下PNG文件格式。 PNG是一种无损压缩的图像文件格式,该格式的第1-8字节保存着PNG署名域,内容如下:

  • 十进制: 137 80 78 71 13 10 26 10
  • 十六进制: 89 50 4e 47 0d 0a 1a 0a

我们的任务就是将这个文件头读取出来。

更详细的关于PNG格式的介绍: * http://www.w3.org/TR/2003/REC-PNG-20031110/ * http://www.libpng.org/pub/png/

读取文件

? PHP

 
1
2
3
4
5
6
$filePath = "icon.png";
//必须使用rb来读取文件,这样能保证跨平台二进制数据的读取安全
$fh = fopen($filePath, "rb");
//仅读取前面的8个字节
$head = fread($fh, );
fclose($fh);

上面的代码已经把我们需要的8个字节读入变量head中了。head是一个保存二进制数据的数组,我们还需要对它做一些操作才能得到我们需要的数据。

unpack

unpack可以将二进制数据解析成关系数组,它接受2个参数,第一个提供解析方式字符串(见下方),第二个参数就提供我们前面读出的head变量就可以了。

  • a:NULL填充的字节串
  • A:空格填充的字节串
  • h:十六进制数,低四位字节优先
  • H:十六进制数,高四位字节优先
  • c:有符号字符
  • C:无符号字符
  • s:有符号短整型(总是16位,机器字节序)
  • S:无符号短整型(总是16位,机器字节序)
  • n:无符号短整型(总是16位,大尾字节序)
  • v:无符号短整型(总是16位,小尾字节序)
  • I:有符号整型(机器相关大小和字节序)
  • I:无符号整型(机器相关大小和字节序)
  • l:有符号长整型(总是32位,机器字节序)
  • L:无符号长整型(总是32位,机器字节序)
  • N:无符号长整型(总是32位,大尾字节序)
  • V:无符号长整型(总是32位,小尾字节序)
  • f:浮点数(机器相关大小和表示)
  • d:双精度数(机器相关大小和表示)
  • x:空字节
  • X:倒退一个字节
  • @:用NULL填充绝对位置

unpack的第一个参数在在使用上有一点点小技巧,下面是范例:

  • C 读取1个字符,返回的数组索引为1
  • C4 读取4个字节,每个字节一个字符,返回的数组索引为1,2,3,4
  • C4head 读取4个字符,每个字节一个字符,返回的数组索引为head1,head2,head3,head4
  • Chead 读取1个字符,返回的数组索引为head

现在试着读取第1个字节:

? PHP

 
1
2
3
$arr = unpack("Chead", $head);
print_r($arr);
//Array ( [head] => 137 )

读取所有的8个字节,用斜杠可以分隔:

? PHP

 
1
2
3
$arr = unpack("Chead/C3string/C4number", $head);
print_r($arr);
//Array ( [head] => 137 [string1] => 80 [string2] => 78 [string3] => 71 [number1] => 13 [number2] => 10 [number3] => 26 [number4] => 10 )

把string开头的键拼成字符串:

? PHP

 
1
2
3
4
5
6
7
$arr = unpack("Chead/C3string/C4number", $head);
for($i=;$i<=;$i++)
{
$type.=chr($arr['string'.$i]);
}
echo $type;
//PNG

bin2hex

上面使用print_r打印出来的内容,都是十进制数字,如果希望直接得到十六进制值,可以使用bin2hex函数。

? PHP

 
1
2
echo bin2hex($head[]);
//89

注意,使用这种方法得到的是字符串,并不是数字。因此下面的条件是不成立的:

? PHP

 
1
2
3
4
if(bin2hex($head[]) == 0x89)
{
echo 'match!';
}

在PHP中读取二进制文件的更多相关文章

  1. PHP将二进制文件存入数据库以及从数据库中读取二进制文件

    <?php $file = 'abcd.sqlite'; mysql_connect('localhost','root','123456'); mysql_select_db('zblog') ...

  2. php中读取文件内容的几种方法

    1.fread string fread ( int $handle , int $length ) fread() 从 handle 指向的文件中读取最多 length 个字节.该函数在读取完最多 ...

  3. java中读取文件以及向文件中追加数据的总结

    package gys; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; imp ...

  4. 用 C# 读取二进制文件

    当想到所有文件都转换为 XML时,确实是一件好事.但是,这并非事实.仍旧还有大量的文件格式不是XML,甚至也不是ASCII.二进制文件仍然在网络中传播,储存在磁盘上,在应用程序之间传递.相比之下,在处 ...

  5. 信息管理代码分析<二>读取二进制文件数据

    first和end做为全局变量,分别指向链表的头和尾.建立链表的方式也比较简易,从二进制文件数据块中,依次从头到尾读取,每读取一个就建立一个结点. /*基本模型*/ EMP *emp1; while( ...

  6. PHP中读取文件的几个方法

    整理了一下PHP中读取文件的几个方法,方便以后查阅. 1.fread string fread ( int $handle , int $length ) fread() 从 handle 指向的文件 ...

  7. 利用Python从文件中读取字符串(解决乱码问题)

    首先声明这篇学习记录是基于python3的. python3中,py文件中默认的文件编码就是unicode,不用像python2中那样加u,比如u'中文'. 不过在涉及路径时,比如C:\Users\A ...

  8. TF从文件中读取数据

    从文件中读取数据 在TensorFlow中进行模型训练时,在官网给出的三种读取方式,中最好的文件读取方式就是将利用队列进行文件读取,而且步骤有两步: 把样本数据写入TFRecords二进制文件 从队列 ...

  9. php中读取文件内容的几种方法。(file_get_contents:将文件内容读入一个字符串)

    php中读取文件内容的几种方法.(file_get_contents:将文件内容读入一个字符串) 一.总结 php中读取文件内容的几种方法(file_get_contents:将文件内容读入一个字符串 ...

随机推荐

  1. Technical support website

    Technical support:Please leave a message if you have any questions or suggestions. email: swvrwafet@ ...

  2. 解决element-ui中el-menu组件作为vue-router模式在刷新页面后default-active属性与当前路由页面不一致问题的方法

    解决办法是给menu的default-active绑定route.path形如:<el-menu :default-active="$route.path" ...>每 ...

  3. Django 02 url路由配置及渲染方式

    Django 02 url路由配置及渲染方式 一.URL #URL #(Uniform Resoure Locator) 统一资源定位符:对可以从互联网上得到的资源的位置和访问方法的一种简洁的表示,是 ...

  4. Linux--6 redis订阅发布、持久化、集群cluster、nginx入门

    一.redis发布订阅 Redis 通过 PUBLISH .SUBSCRIBE 等命令实现了订阅与发布模式. 其实从Pub/Sub的机制来看,它更像是一个广播系统,多个Subscriber可以订阅多个 ...

  5. java监听器原理理解与实现

    监听器模型涉及以下三个对象,模型图如下: (1)事件:用户对组件的一个操作,称之为一个事件(2)事件源:发生事件的组件就是事件源(3)事件监听器(处理器):监听并负责处理事件的方法 执行顺序如下: 1 ...

  6. FZU Problem 2244 Daxia want to buy house

    模拟题,注意: 1.那两个贷款都是向银行贷的,就是两个贷款的总额不能超过70%,就算公积金贷款能贷也不行,我开始的时候以为公积金贷款是向公司借的,,欺负我这些小白嘛.... 2.最坑的地方 *0.7是 ...

  7. ubuntu网络已禁用解决办法

    1.首先停掉network-manager这个服务 sudo service network-manager stop 2.删除掉NetworkManager.state这个文件 sudo rm /v ...

  8. CentOS mini 和 nginx 的安装和配置要点

    1.安装VMware Player    版本:5.0.2 build-1031769 2.安装XShell    版本:Build 0126 3.安装CentOS    版本:6.4-x86_64- ...

  9. linux下的idea的界面问题,错位以及各种...

    问题 ’ 方法 主题设置为GTK,多余的点会消失,而且字体也会好很多

  10. jquery--实现类似淘宝星星评分功能

    -   不正之处,欢迎指正.^-^.好绕的话 贴码.html <body> <div id="div"> <ul> <li>☆< ...