2009-06-29 24 views
55

Tôi đang điều tra mã hóa trong PHP5. Có cách nào để có được một bãi chứa hex thô của một chuỗi? tức là một biểu diễn hex của mỗi byte (không phải ký tự) trong một chuỗi?Làm thế nào tôi có thể nhận được một kết xuất hex của một chuỗi trong PHP?

+1

Một số thoải mái chút công cụ trực tuyến http://srsbiz.pl/utils/hexit .php và nguồn php của nó: gist.github.com/4639219 - có thể hữu ích, tín dụng/nhờ @ dev-null-dweller – hakre

+0

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

Trả lời

80
echo bin2hex($string); 

hay:

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

$string là biến chứa dữ liệu vào.

+12

Hoặc phương pháp tiếp cận chức năng hơn: print_r (array_map ('dechex', array_map ('ord', str_split ($ string)))); –

66

Đối gỡ làm việc với các giao thức nhị phân, tôi cần một bãi chứa HEX truyền thống hơn, vì vậy tôi đã viết chức năng này:

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

Điều này tạo ra một bãi chứa HEX truyền thống hơn, như thế này:

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] 

Lưu ý rằng các ký tự không hiển thị được thay thế bằng dấu chấm - bạn có thể thay đổi số byte trên mỗi dòng (độ rộng $) và ký tự đệm ($ pad) cho phù hợp với nhu cầu của bạn. Tôi đã bao gồm một đối số $ newline, vì vậy bạn có thể vượt qua "<br/>" nếu bạn cần hiển thị đầu ra trong trình duyệt.

Hy vọng điều này hữu ích :-)

+2

+1 tuyệt vời. Quá tuyệt vời. Tôi đã làm việc bốn giờ + trên một cái gì đó và điều này chỉ thúc đẩy tôi. Dù sao, tôi thấy rằng việc lặp lại một thẻ trước làm cho nó hiển thị tốt hơn trong một trình duyệt. Hoặc sử dụng br newline. Tôi mới làm điều này và tự hỏi làm thế nào tôi có thể giải mã các ký tự không nhìn thấy được. TNX. – frostymarvelous

+0

Yêu thích nó! Cần vài cải tiến, nhưng như là một cơ sở của công cụ gỡ lỗi - nó là một hoàn hảo! –

+2

@frostymarvelous cho đầu ra chẩn đoán chỉ văn bản trong trình duyệt, hãy thử 'header ('Content-type: text/plain');' - có ích :-) –

3

Trong khi gỡ rối giao thức nhị phân, tôi cũng cần có hexdump(). Tôi quyết định xuất bản giải pháp của mình như một gói PEAR vì nó chắc chắn hữu ích. Bạn cũng có thể duyệt mã tại github.

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

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

Ngoài giải pháp mindplays nó hỗ trợ propper rendering của dòng cuối cùng và params bổ sung. Ngoài ra các gói phần mềm có chứa một php thực thi được đặt tên phphd cho hexdumps trên cmdline. Điều này có thể hữu ích trên Windows Systems :)

@ mindplay.dk: Cảm ơn ý tưởng strtr(). Nó xuất hiện nhanh hơn một chút so với nỗ lực cũ của tôi. Tích hợp vào phiên bản của tôi. (Sử dụng bộ đệm dịch đã giảm) ..

Vui vẻ!

1

"Functional" phiên bản:

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

vay từ Ionuţ G. Stan của comment, dòng cuối cùng có thể là như sau:

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

Đó là năm sau, nhưng trong trường hợp những người khác đang tìm kiếm điều này nữa, tôi đã tự do sửa đổi mã của mindplay.dk để làm cho nó chấp nhận các tùy chọn khác nhau và mô phỏng đầu ra của lệnh BSD hexdump -C file:

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

và đây là một bãi chứa hex của một tập tin nhỏ:

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 

và đây là thử nghiệm 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

Dòng cuối cùng 00000086 là vô dụng. –

+3

Nói với tác giả của lệnh hexdump BSD. Dòng cuối cùng cho biết kích thước tệp. –

Các vấn đề liên quan