Wie kann ich einen Hex-Dump eines Strings in PHP erhalten?
70
Ich untersuche Codierungen in PHP5. Gibt es eine Möglichkeit, einen rohen Hex-Dump eines Strings zu erhalten? dh eine hexadezimale Darstellung jedes der Bytes (keine Zeichen) in einer Zeichenfolge?
Einige nette kleine Online-Tool srsbiz.pl/utils/hexit.php und es ist PHP-Quelle: gist.github.com/4639219 - könnte nützlich sein, Credits / danke @ dev-null-
Beachten Sie, dass nicht sichtbare Zeichen durch einen Punkt ersetzt werden. Sie können die Anzahl der Bytes pro Zeile ($ width) und das Auffüllzeichen ($ pad) entsprechend Ihren Anforderungen ändern. Ich habe ein $ newline-Argument eingefügt, damit Sie übergeben können, "<br/>"wenn Sie die Ausgabe in einem Browser anzeigen müssen.
+1 ausgezeichnet. Zu gut. Ich habe über vier Stunden an etwas gearbeitet und das hat mich nur beflügelt. Wie auch immer, ich habe festgestellt, dass das Echo eines Pre-Tags die Anzeige in einem Browser verbessert. Oder mit br newline. Ich bin neu in diesem Bereich und frage mich, wie ich die nicht sichtbaren Zeichen entschlüsseln kann. TNX.
frostymarvelous
Liebe es! Benötigt einige Verbesserungen, aber als Basis für das Debugging-Tool - es ist perfekt!
Ruben Kazumov
3
@ Frostymarvelous für Nur-Text-Diagnose-Ausgabe in einem Browser, versuchen Sie header('Content-type: text/plain');- ist praktisch :-)
mindplay.dk
Dies ist im Wesentlichen wie einod -tx1z
Walter Tross
Bitte geben Sie einen Wert für $ data an.
SwR
9
Es ist Jahre später, aber falls andere auch danach suchen, habe ich mir erlaubt, den Code von mindplay.dk so zu ändern, dass er verschiedene Optionen akzeptiert und die Ausgabe des BSD-Befehls hexdump -C file simuliert:
/**
* 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
*/functionhex_dump($string, array$options = null) {
if (!is_scalar($string)) {
thrownewInvalidArgumentException('$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_linesas$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;
}
Sagen Sie das dem Autor des BSD-Befehls hexdump. Die letzte Zeile gibt die Dateigröße an.
Interner
4
Beim Debuggen eines Binärprotokolls brauchte ich auch einen hexdump (). Ich habe beschlossen, meine Lösung als PEAR-Paket zu veröffentlichen, da sie definitiv nützlich ist. Sie können den Code auch bei github durchsuchen.
Zusätzlich zur Mindplays-Lösung unterstützt es das korrekte Rendern der letzten Zeile und zusätzliche Parameter. Das Paket enthält auch eine ausführbare PHP-Datei mit dem Namen phphd für hexdumps auf cmdline. Dies könnte auf Windows-Systemen hilfreich sein :)
@ mindplay.dk: Danke für die strtr () Idee. Es schien etwas schneller als mein früherer Versuch. Integrierte das in meine Version. (Verwenden eines verringerten Übersetzungspuffers) ..
Während dieser Code die Frage lösen kann, einschließlich einer Erklärung, wie und warum dies das Problem löst, würde dies wirklich dazu beitragen, die Qualität Ihres Beitrags zu verbessern, und wahrscheinlich zu mehr Up-Votes führen. Denken Sie daran, dass Sie in Zukunft die Frage für die Leser beantworten, nicht nur für die Person, die jetzt fragt. Bitte bearbeiten Sie Ihre Antwort, um Erklärungen hinzuzufügen und anzugeben, welche Einschränkungen und Annahmen gelten.
Antworten:
echo bin2hex($string);
oder:
for ($i = 0; $i < strlen($string); $i++) { echo str_pad(dechex(ord($string[$i])), 2, '0', STR_PAD_LEFT); }
$string
ist die Variable, die Eingabe enthält.quelle
Für das Debuggen mit Binärprotokollen benötigte ich einen traditionelleren HEX-Dump, also schrieb ich diese Funktion:
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; } }
Dies erzeugt einen traditionelleren HEX-Dump wie folgt:
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]
Beachten Sie, dass nicht sichtbare Zeichen durch einen Punkt ersetzt werden. Sie können die Anzahl der Bytes pro Zeile ($ width) und das Auffüllzeichen ($ pad) entsprechend Ihren Anforderungen ändern. Ich habe ein $ newline-Argument eingefügt, damit Sie übergeben können,
"<br/>"
wenn Sie die Ausgabe in einem Browser anzeigen müssen.Hoffe das ist nützlich :-)
quelle
header('Content-type: text/plain');
- ist praktisch :-)od -tx1z
Es ist Jahre später, aber falls andere auch danach suchen, habe ich mir erlaubt, den Code von mindplay.dk so zu ändern, dass er verschiedene Optionen akzeptiert und die Ausgabe des BSD-Befehls hexdump -C file simuliert:
/** * 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; }
und dies ist ein Hex-Dump einer kleinen Datei:
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
und das ist der phpunit test:
<?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); } }
quelle
Beim Debuggen eines Binärprotokolls brauchte ich auch einen hexdump (). Ich habe beschlossen, meine Lösung als PEAR-Paket zu veröffentlichen, da sie definitiv nützlich ist. Sie können den Code auch bei github durchsuchen.
PEAR: http://www.metashock.de/pear
GitHub: http://www.github.com/metashock/Hexdump
Zusätzlich zur Mindplays-Lösung unterstützt es das korrekte Rendern der letzten Zeile und zusätzliche Parameter. Das Paket enthält auch eine ausführbare PHP-Datei mit dem Namen phphd für hexdumps auf cmdline. Dies könnte auf Windows-Systemen hilfreich sein :)
@ mindplay.dk: Danke für die strtr () Idee. Es schien etwas schneller als mein früherer Versuch. Integrierte das in meine Version. (Verwenden eines verringerten Übersetzungspuffers) ..
Habe Spaß!
quelle
"Funktionale" Version:
$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))));
In Anlehnung an den Kommentar von Ionuț G. Stan könnte die letzte Zeile wie folgt lauten:
}, array_map('dechex', array_map('ord', str_split($s)))));
quelle
echo implode(array_map( fn ($a, $b) => sprintf("%-26s%-8s\n", $a, $b), str_split(implode(' ', str_split(bin2hex($string), 2)), 24), str_split($string, 8) ));
quelle