Parser um arquivo binário em PHP

Abril 2017

Suponhamos que você tenha gravado dados binários em um arquivo, ou seja, uma gravação bruta que não é traduzida em texto.

Isso é algo que normalmente é feito com algumas linguagens de baixo nível como a C ou a Pascal.


Veja um exemplo em C, suponhamos que você queira salvar o valor 500 em um arquivo, o código será o seguinte:

#include <stdio.h> 

int main() 
{ 
    int val = 500; 
    FILE *fp = fopen("arquivo", "wb"); 
     
    fwrite(&val, sizeof(int), 1, fp); //Gravação do val no "arquivo" 
    fclose(fp); 
    return 0; 
}


Se você abrir o arquivo salvo com um editor de texto, você poderá encontrar um jargão, porque o seu valor não foi salvo como texto, mas binário.

Ora, se você usar uma linguagem como a PHP pode ser que você precise recuperar os valores armazenados em binário um dia desses. No entanto, a PHP só lê e escreve nos arquivos em forma de texto. Você deverá passar por uma função específica para recuperar seus valores corretamente.

Solução


A função unpack () existe para resolver este tipo de problema.

Como primeiro argumento, você deve assinalar o tipo de dado que você quer recuperar e como segundo, a string na qual você recuperará os dados.

O tipo de dado a ser recuperado deve ser detalhado em forma de um caractere simbólico. Por exemplo, para recuperar um inteiro assinado (tipo int em C), use o caractere "i".


Portanto, se nos referimos ao arquivo que acabamos de salvar no exemplo acima, veja o código para recuperar o nosso valor:
<?php 
$fp = fopen("arquivo", "rb"); 
$data = fread($fp, 4); //4 é o tamanho em bytes de um inteiro em um PC 32 bits. 
$número = unpack("i", $data); 
echo $número [1]; //aparecerá 500 
?>

Atenção, as seguintes observações são muito importantes:
  • O tamanho dos dados pode mudar dependendo arquiteturas de processadores. Um mesmo programa escrito em C usará inteiros de tamanhos diferentes passando de um PC de 32 bits para 64 bits. O tamanho também poderá ser diferente de uma arquitetura de processador para outra (Sparc, ARM, PowerPC, etc ...).
  • O arranjo dos dados não poderá ser o mesmo. Algumas máquinas armazenam os dados em Big Endian, outras em Little Endian.
  • O tamanho dos dados também pode variar conforme o compilador.
  • A função "unpack" retorna uma tabela para permitir a utilização um pouco mais elaborada do que a indicada aqui como exemplo. No nosso caso, com um único valor solicitado, o nosso valor está situado no offset 1 da tabela.
  • O tamanho dos dados pode mudar dependendo arquiteturas de processadores. Mesmo programa escrito em C usa inteiros de diferentes tamanhos a partir de um PC de 32 bits para 64 bits. O tamanho também pode ser diferente de uma arquitetura de processador para outro (Sparc, ARM, PowerPC, etc ...).

Equivalências formatos / tipos de dados para arquitetura PC 32 bits


Os formatos utilizáveis estão documentados neste endereço.
Veja uma pequena tabela de equivalência para os dados gravados por um programa em C compilado para um PC de 32 bits.
Cuidado, essas equivalências não são necessariamente válidas com o compilador usado para compilar o programa que produziu o arquivo, sem contar com outros parâmetros que entram em linha de conta. Além disso, recomendo que você teste o seu programa, tanto com os pequenos valores quanto com os grandes.
Da mesma forma, essas equivalências são dadas teoricamente, eu não as testei.

char : c
unsigned char : C
short : s
unsigned short : S
int : l
unsigned int : L
float : f
double : d


Tradução feita por Lucia Maurity y Nouira

Veja também

Artigo original publicado por . Tradução feita por pintuda. Última modificação: 26 de junho de 2011 às 11:15 por pintuda.
Este documento, intitulado 'Parser um arquivo binário em PHP', está disponível sob a licença Creative Commons. Você pode copiar e/ou modificar o conteúdo desta página com base nas condições estipuladas pela licença. Não se esqueça de creditar o CCM (br.ccm.net) ao utilizar este artigo.