2009-06-29 9 views
55

Badam kodowanie w PHP5. Czy istnieje sposób, aby uzyskać nieprzetworzone szesnastkowe ciąg znaków? tj. heksadecymalną reprezentację każdego z bajtów (nie znaków) w ciągu znaków?Jak mogę uzyskać zrzut heksadecymalny ciągu znaków w PHP?

+1

Niektóre miły mały narzędzie online http://srsbiz.pl/utils/hexit .php i jego źródło php: gist.github.com/4639219 - może być przydatny, kredyty/podziękowania @ dev-null-dweller – hakre

+0

https://github.com/clue/php-hexdump – bishop

Odpowiedz

80
echo bin2hex($string); 

czyli

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

$string jest zmienną, która zawiera wejście.

+12

Lub bardziej funkcjonalne podejście: print_r (array_map ('dechex', array_map ("ord", str_split ($ string)))); –

66

Do debugowania pracy z protokołów binarnych, potrzebowałem bardziej tradycyjny Hex Dump, więc napisałem tę funkcję:

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; 
    } 
} 

Daje to bardziej tradycyjne Hex Dump, tak:

hex_dump($data); 

=> 

0 : 05 07 00 00 00 64 65 66 61 75 6c 74 40 00 00 00 [[email protected]] 
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] 

Zwróć uwagę, że niewidoczne znaki są zastępowane kropką - możesz zmienić liczbę bajtów na linię (szerokość $) i znak wypełnienia ($ pad) w zależności od potrzeb. Zawarłem argument $ newline, więc możesz przekazać "<br/>", jeśli chcesz wyświetlić dane wyjściowe w przeglądarce.

Nadzieja ta jest przydatna :-)

+2

+1 doskonały. Zbyt piękne. Pracowałem cztery godziny na coś i to tylko mnie wzmocniło. W każdym razie, stwierdziłem, że echo tagu pre sprawia, że ​​wyświetla się lepiej w przeglądarce. Lub używając br nowej linii. Jestem nowy w tym i zastanawiam się, jak mogę odszyfrować niewidoczne znaki. TNX. – frostymarvelous

+0

Uwielbiam to! Wymaga kilku ulepszeń, ale jako bazy narzędzia do debugowania - jest to idealne! –

+2

@frostymarvelous dla tekstowego wyjścia diagnostycznego w przeglądarce, spróbuj 'header ('Content-type: text/plain');' - przydaje się :-) –

3

Podczas debugowania protokołu binarnego Musiałem hexdump() też. Zdecydowałem się opublikować moje rozwiązanie jako pakiet PEAR, ponieważ jest to zdecydowanie przydatne. Możesz również przeglądać kod na github.

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

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

Ponadto rozwiązanie to umożliwia oddawanie mindplays Właściwa ostatniej linii i Dodatkowe parametry. Również pakiet zawiera plik wykonywalny php o nazwie phphd dla hexdumps na cmdline. To może być pomocne w systemach Windows :)

@ mindplay.dk: Dzięki za pomysł strtr(). Wyglądało to trochę szybciej niż moja poprzednia próba. Zintegrowałem to z moją wersją. (Używając zmniejszonego bufora tłumaczenia) ..

Baw się dobrze!

1

"Functional" wersja:

$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)))); 

Pożyczanie od Ionuţ G. Stana comment, ostatnia linia może być następująca:

}, array_map('dechex', array_map('ord', str_split($s))))); 
4

Jest to rok później, ale w przypadku innych szukasz to też, mogłem zmodyfikować kod mindplay.dk, aby mógł akceptować różne opcje i symulować wyjście polecenia hexdump - plik:

/** 
* 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; 
} 

i to jest nora hex małego pliku:

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 

i to jest test 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); 
    } 
} 
+0

Ostatnia linia 00000086 jest bezużyteczna. –

+3

Powiedz to autorowi hexdump polecenia BSD. Ostatni wiersz wskazuje rozmiar pliku. –

Powiązane problemy