Pergunta

Estou investigando codificações em PHP5. Existe alguma maneira de obter um despejo hex crua de uma string? isto é, uma representação do hex de cada um dos bytes (não caracteres) em uma cadeia?

Foi útil?

Solução

echo bin2hex($string);

ou

for ($i = 0; $i < strlen($string); $i++) {
    echo str_pad(dechex(ord($string[$i])), 2, '0', STR_PAD_LEFT);
}

$string é a variável que contém entrada.

Outras dicas

Para depurar o trabalho com protocolos binários, eu precisava de um despejo HEX mais tradicional, então eu escrevi essa função:

function hex_dump($data, $newline="\n")
{
  static $from = '';
  static $to = '';

  static $width = 16; # number of bytes per line

  static $pad = '.'; # padding for non-visible characters

  if ($from==='')
  {
    for ($i=0; $i<=0xFF; $i++)
    {
      $from .= chr($i);
      $to .= ($i >= 0x20 && $i <= 0x7E) ? chr($i) : $pad;
    }
  }

  $hex = str_split(bin2hex($data), $width*2);
  $chars = str_split(strtr($data, $from, $to), $width);

  $offset = 0;
  foreach ($hex as $i => $line)
  {
    echo sprintf('%6X',$offset).' : '.implode(' ', str_split($line,2)) . ' [' . $chars[$i] . ']' . $newline;
    $offset += $width;
  }
}

Isso produz um despejo HEX mais tradicional, como este:

hex_dump($data);

=>

 0 : 05 07 00 00 00 64 65 66 61 75 6c 74 40 00 00 00 [.....default@...]
10 : 31 42 38 43 39 44 30 34 46 34 33 36 31 33 38 33 [1B8C9D04F4361383]
20 : 46 34 36 32 32 46 33 39 32 46 44 38 43 33 42 30 [F4622F392FD8C3B0]
30 : 45 34 34 43 36 34 30 33 36 33 35 37 45 35 33 39 [E44C64036357E539]
40 : 43 43 38 44 35 31 34 42 44 36 39 39 46 30 31 34 [CC8D514BD699F014]

Note que os caracteres não-visíveis são substituídos por um período - você pode alterar o número de bytes por linha ($ width) e caracter de preenchimento ($ pad) para atender às suas necessidades. Eu incluí um argumento $ nova linha, para que possa passar "<br/>" se você precisa exibir a saída em um navegador.

Hope isso é útil: -)

É anos mais tarde, mas no caso dos outros estão procurando por isso, também, tomei a liberdade de modificar o código de mindplay.dk para torná-lo aceitar várias opções e simular a saída do arquivo hexdump -C comando BSD:

/**
* Dumps a string into a traditional hex dump for programmers,
* in a format similar to the output of the BSD command hexdump -C file.
* The default result is a string.
* Supported options:
* <pre>
*   line_sep        - line seperator char, default = "\n"
*   bytes_per_line  - default = 16
*   pad_char        - character to replace non-readble characters with, default = '.'
* </pre>
*
* @param string $string
* @param array $options
* @param string|array
*/
function hex_dump($string, array $options = null) {
    if (!is_scalar($string)) {
        throw new InvalidArgumentException('$string argument must be a string');
    }
    if (!is_array($options)) {
        $options = array();
    }
    $line_sep       = isset($options['line_sep'])   ? $options['line_sep']          : "\n";
    $bytes_per_line = @$options['bytes_per_line']   ? $options['bytes_per_line']    : 16;
    $pad_char       = isset($options['pad_char'])   ? $options['pad_char']          : '.'; # padding for non-readable characters

    $text_lines = str_split($string, $bytes_per_line);
    $hex_lines  = str_split(bin2hex($string), $bytes_per_line * 2);

    $offset = 0;
    $output = array();
    $bytes_per_line_div_2 = (int)($bytes_per_line / 2);
    foreach ($hex_lines as $i => $hex_line) {
        $text_line = $text_lines[$i];
        $output []=
            sprintf('%08X',$offset) . '  ' .
            str_pad(
                strlen($text_line) > $bytes_per_line_div_2
                ?
                    implode(' ', str_split(substr($hex_line,0,$bytes_per_line),2)) . '  ' .
                    implode(' ', str_split(substr($hex_line,$bytes_per_line),2))
                :
                implode(' ', str_split($hex_line,2))
            , $bytes_per_line * 3) .
            '  |' . preg_replace('/[^\x20-\x7E]/', $pad_char, $text_line) . '|';
        $offset += $bytes_per_line;
    }
    $output []= sprintf('%08X', strlen($string));
    return @$options['want_array'] ? $output : join($line_sep, $output) . $line_sep;
}

e este é um hexadecimal de um arquivo pequeno:

00000000  89 50 4e 47 0d 0a 1a 0a  00 00 00 0d 49 48 44 52  |.PNG........IHDR|
00000010  00 00 00 10 00 00 00 10  02 03 00 00 00 62 9d 17  |.............b..|
00000020  f2 00 00 00 09 50 4c 54  45 04 04 04 99 99 cc d7  |.....PLTE.......|
00000030  d7 d7 2a 66 f6 6b 00 00  00 38 49 44 41 54 78 9c  |..*f.k...8IDATx.|
00000040  63 08 05 02 06 24 22 0b  44 24 01 89 ac a4 69 4b  |c....$".D$....iK|
00000050  19 1a 16 68 70 31 74 29  75 2c 42 22 1a 16 75 00  |...hp1t)u,B"..u.|
00000060  c5 22 33 96 32 74 86 46  4c 65 58 19 1a 35 15 61  |."3.2t.FLeX..5.a|
00000070  00 00 df be 19 a6 2e 62  80 87 00 00 00 00 49 45  |.......b......IE|
00000080  4e 44 ae 42 60 82                                 |ND.B`.|
00000086

e este é o teste phpunit:

<?php
if (isset($argv)) {
    print "Running outside of phpunit. Consider using phpunit.\n";
    class PHPUnit_Framework_TestCase {}
}


class Test extends PHPUnit_Framework_TestCase
{
    const FUNCTION_NAME = 'hex_dump';
    const DATA_BASE64 = '
        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAgMAAABinRfyAAAACVBMVEUEBASZmczX19cqZvZrAAAA
        OElEQVR4nGMIBQIGJCILRCQBiaykaUsZGhZocDF0KXUsQiIaFnUAxSIzljJ0hkZMZVgZGjUVYQAA
        374Zpi5igIcAAAAASUVORK5CYII=';
    private $expect = array(
        '00000000  89 50 4e 47 0d 0a 1a 0a  00 00 00 0d 49 48 44 52  |.PNG........IHDR|',
        '00000010  00 00 00 10 00 00 00 10  02 03 00 00 00 62 9d 17  |.............b..|',
        '00000020  f2 00 00 00 09 50 4c 54  45 04 04 04 99 99 cc d7  |.....PLTE.......|',
        '00000030  d7 d7 2a 66 f6 6b 00 00  00 38 49 44 41 54 78 9c  |..*f.k...8IDATx.|',
        '00000040  63 08 05 02 06 24 22 0b  44 24 01 89 ac a4 69 4b  |c....$".D$....iK|',
        '00000050  19 1a 16 68 70 31 74 29  75 2c 42 22 1a 16 75 00  |...hp1t)u,B"..u.|',
        '00000060  c5 22 33 96 32 74 86 46  4c 65 58 19 1a 35 15 61  |."3.2t.FLeX..5.a|',
        '00000070  00 00 df be 19 a6 2e 62  80 87 00 00 00 00 49 45  |.......b......IE|',
        '00000080  4e 44 ae 42 60 82                                 |ND.B`.|',
        '00000086',
    );

    public function testRequire() {
        $file = __DIR__ . '/' . static::FUNCTION_NAME . '.php';
        $this->assertFileExists($file);
        include($file);
        $this->assertTrue(function_exists(static::FUNCTION_NAME));
    }

    public function testString() {
        $func = static::FUNCTION_NAME;
        $data = base64_decode(static::DATA_BASE64);
        if (!is_string($data)) {
            throw new Exception('Unable to decode base64 encoded test data');
        }
        $dump = $func($data);
        //var_export($dump);
        $this->assertTrue(is_string($dump));
        $this->assertEquals($dump, join("\n", $this->expect) . "\n");
    }

}


if (isset($argv)) {
    $func = Test::FUNCTION_NAME;
    require_once($func . '.php');
    if (count($argv) < 2) {
        print "Pass arguments file, from, length.\n";
    }
    else {
        $file = $argv[1];
        if (!file_exists($file)) {
            die("File not found: $file\n");
        }
        $from   = isset($argv[2]) && preg_match('/^\d{1,9}$/', $argv[2]) ? intval($argv[2]) : null;
        $len    = isset($argv[3]) && preg_match('/^\d{1,9}$/', $argv[3]) ? intval($argv[3]) : filesize($file);
        $h = fopen($file, 'r');
        if ($from) {
            fseek($h, $from);
        }
        $data = fread($h, $len);
        fclose($h);
        $dump = hex_dump($data);
        print $dump;
        //$dump = hex_dump($data, array('want_array' => true));
        //print_r($dump);
    }
}

Durante a depuração um protocolo binário eu precisava de um hexdump () também. Eu decidi publicar minha solução como um pacote PEAR como é definitivamente útil. Você também pode procurar o código no github.

PERA: http://www.metashock.de/pear

GitHub: http://www.github.com/metashock/Hexdump

Além de solução mindplays ele suporta renderização propper da última linha e parâmetros adicionais. Além disso, o pacote contém um executável php chamado phphd para hexdumps no cmdline. Isso pode ser útil em sistemas Windows:)

@ mindplay.dk: Obrigado pela ideia strtr (). Parecia leve mais rápido do que meu antigo tentativa. Integrado que na minha versão. (Usando uma diminuição do tampão de tradução) ..

Have Fun!

versão "funcional":

$s = "\x04\x00\xa0\x00";
echo implode(' ', array_map(function($char) {
    # return sprintf('%02s', $char);
    return str_pad($char, 2, '0', STR_PAD_LEFT);
}, array_map('dechex', unpack('C*', $s))));

O empréstimo de Ionut G. Stan comentário , a última linha pode ser a seguinte:

}, array_map('dechex', array_map('ord', str_split($s)))));
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top