How can I get a hex dump of a string in PHP?

后端 未结 6 1269
陌清茗
陌清茗 2020-11-22 07:50

I\'m investigating encodings in PHP5. Is there some way to get a raw hex dump of a string? i.e. a hex representation of each of the bytes (not characters) in a string?

6条回答
  •  死守一世寂寞
    2020-11-22 08:03

    It's years later, but in case others are searching for this too, I took the liberty to modify mindplay.dk's code to make it accept various options and simulate the output of the BSD command 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:
    * 
    *   line_sep        - line seperator char, default = "\n"
    *   bytes_per_line  - default = 16
    *   pad_char        - character to replace non-readble characters with, default = '.'
    * 
    * * @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; }

    and this is a hex dump of a small file:

    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
    

    and this is the phpunit test:

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

提交回复
热议问题