在PHP中讀取二進制文件

不少時候,數據並非用文本的方式保存的,這就須要將二進制數據讀取出來,還原成咱們須要的格式。PHP在二進制處理方面也提供了強大的支持。javascript

 

任務

下面以讀取並分析一個PNG圖像的文件頭爲例,講解如何使用PHP讀取和分析二進制文件。php

涉及函數

PNG格式簡介

爲了完成任務,下面簡單介紹一下PNG文件格式。 PNG是一種無損壓縮的圖像文件格式,該格式的第1-8字節保存着PNG署名域,內容以下:java

  • 十進制: 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/安全

讀取文件

? View Code PHP
 
1
2
3
4
5
6
$filePath = "icon.png";
//必須使用rb來讀取文件,這樣能保證跨平臺二進制數據的讀取安全
$fh = fopen($filePath, "rb");
//僅讀取前面的8個字節
$head = fread($fh, 8);
fclose($fh);

上面的代碼已經把咱們須要的8個字節讀入變量head中了。head是一個保存二進制數據的數組,咱們還須要對它作一些操做才能獲得咱們須要的數據。函數

unpack

unpack能夠將二進制數據解析成關係數組,它接受2個參數,第一個提供解析方式字符串(見下方),第二個參數就提供咱們前面讀出的head變量就能夠了。spa

  • 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的第一個參數在在使用上有一點點小技巧,下面是範例:.net

  • C 讀取1個字符,返回的數組索引爲1
  • C4 讀取4個字節,每一個字節一個字符,返回的數組索引爲1,2,3,4
  • C4head 讀取4個字符,每一個字節一個字符,返回的數組索引爲head1,head2,head3,head4
  • Chead 讀取1個字符,返回的數組索引爲head

如今試着讀取第1個字節:code

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

讀取全部的8個字節,用斜槓能夠分隔:blog

? View Code 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開頭的鍵拼成字符串:

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

bin2hex

上面使用print_r打印出來的內容,都是十進制數字,若是但願直接獲得十六進制值,能夠使用bin2hex函數。

? View Code PHP
 
1
2
echo bin2hex($head[0]);
//89

注意,使用這種方法獲得的是字符串,並非數字。所以下面的條件是不成立的:

? View Code PHP
 
1
2
3
4
if(bin2hex($head[0]) == 0x89)
{
    echo 'match!';
}
相關文章
相關標籤/搜索