Форум dkLab и Denwer
Здесь общаются Web-разработчики.
Генеральный спонсор:
Хостинг «Джино»

HEX-представление строки (Navigator)
Author Message
Navigator
Участник форума



Joined: 27 Nov 2004
Posts: 221
Карма: -12
   поощрить/наказать

Location: Павловский Посад

PostPosted: Tue Aug 02, 2005 12:33 pm (написано за 2 минуты 56 секунд)
   Post subject: HEX-представление строки
Reply with quote

Написал тут небольшую функцию, позволяющую посмотреть бинарную строку в шестнадцатеричном виде (как в hex-редакторах):
Code (php): скопировать код в буфер обмена
function hexDump($raw) {
        $raw = (string)$raw;
        $len = strlen (www.php.net/strlen)($raw);
        $raz = ceil (www.php.net/ceil)($len / 16);
        $i = 0;
        $ret = "Length: $len\n";
        while ($i++ < $raz) {
                $tempHex = "";
                $tempRaw = "";
                $tempStr = substr (www.php.net/substr)($raw, 16 * ($i - 1), 16);
                $j = -1;
                while ($j++ < 16) {
                        if (!isset (www.php.net/isset)($tempStr{$j})) break;
                        $ord = dechex (www.php.net/dechex)(ord (www.php.net/ord)($tempStr{$j}));
                        if (strlen (www.php.net/strlen)((string)$ord) < 2) $ord = "0$ord";
                        $tempHex .= $ord." ";
                        $tempRaw .= preg_replace (www.php.net/preg_replace)("#[^a-z-0-9\-=\+\?_!@\#\$%\^&\*\(\)\:~]#i",".",$tempStr{$j});
                }
                if (strlen (www.php.net/strlen)($tempHex) < 48) while (strlen (www.php.net/strlen)($tempHex) < 48) $tempHex .= " ";
                if (strlen (www.php.net/strlen)($tempRaw) < 16) while (strlen (www.php.net/strlen)($tempRaw) < 16) $tempRaw .= " ";
                $ret .= "$tempHex| $tempRaw |\n";
        }
        return $ret;
}
Работает так:
Code (php): скопировать код в буфер обмена
print (www.php.net/print) "<pre>".hexDump(\n\r\t    ,  \x00\r")."</pre>";
Этот пример выведет:
Code (any language): скопировать код в буфер обмена
Length: 68
fd f2 ee 20 f2 e5 f1 f2 ee e2 e0 ff 20 f1 f2 f0 | это.тестовая.стр |
ee ea e0 0a 0d 09 ee ed e0 20 ec ee e6 e5 f2 20 | ока...она.может. |
f1 ee e4 e5 f0 e6 e0 f2 fc 20 eb fe e1 fb e5 20 | содержать.любые. |
f1 e8 ec e2 ee eb fb 2c 20 e4 e0 e6 e5 20 ed f3 | символы..даже.ну |
eb e8 00 0d                                     | ли..             |
Back to top
View user's profile Send private message
Юрий Насретдинов
Модератор



Joined: 13 Mar 2003
Posts: 8642
Карма: 198
   поощрить/наказать

Location: 007 495

PostPosted: Tue Aug 09, 2005 10:42 pm (спустя 7 дней 10 часов 8 минут; написано за 4 минуты 32 секунды)
   Post subject:
Reply with quote

Хм, решил написать свою функцию, делающую то же самое, думал, что она будет работать быстрее... Оказалось, работает медленнее, причём чем больше строка, тем больше отрыв:
Quote:
0.378108978271 sec - hexView //README.txt Денвера
0.313061952591 sec - hexDump
0.00113201141357 sec - hexView //очень коротенькая тестовая строчка
0.00104999542236 sec - hexDump
Вот собственно сама функция:
Code (php): скопировать код в буфер обмена
function hexView($str,$row=16)
{
        $ret='';
        $hx=array (www.php.net/array)();
        $l=strlen (www.php.net/strlen)($str);
       
        for($i=0;$i<$l;$i++)
        {
                $r=floor (www.php.net/floor)($i/$row);
                $hx[$r][$i]=sprintf (www.php.net/sprintf)('%02X',$c=ord (www.php.net/ord)($str[$i]));
                if($c<=32 || in_array (www.php.net/in_array)($c,array (www.php.net/array)(127,152,173))) $str[$i]='.';
        }
       
        // добавляем «пустые» куски
       
        $rows=ceil (www.php.net/ceil)($l/$row);
        if($l%$row!=0)
        {
                $tmp=$row-$l%$row;
                $str.=str_repeat (www.php.net/str_repeat)(' ',$tmp);
                for($i=0;$i<$tmp;$i++) $hx[$r][]='  ';
        }
       
        //выводим полученный результат (форматирование может быть абсолютно произвольным)
       
        $ret.='<pre>+'.str_repeat('-',$row*3+1)."+".str_repeat('-',$row+2)."+\n";
        for($i=0;$i<$rows;$i++)
        {
                $ret.='| '.implode(' ',$hx[$i]).' | '.substr($str,$i*$row,$row)." |\n";
        }
        return $ret.'+'.str_repeat('-',$row*3+1)."+".str_repeat('-',$row+2).'+</pre>';
}
Собственно, разница в том, что она немного красивее форматирует вывод (в том числе показывает большее количество символов), и позволяет задавать разную ширину столбцов. Ну
а также, ИМХО, сам код будет покрасивее и логичнее.

Пример работы (начало архива dnsearch_1_0.zip):
Code (any language): скопировать код в буфер обмена
А вот это выдаёт hexDump:
Code (any language): скопировать код в буфер обмена
Back to top
View user's profile Send private message Send e-mail
Rumata
Профессионал



Joined: 17 Aug 2003
Posts: 1850
Карма: 185
   поощрить/наказать


PostPosted: Mon Aug 15, 2005 8:10 pm (спустя 5 дней 21 час 28 минут; написано за 2 минуты 22 секунды)
   Post subject:
Reply with quote

можно и мне?
мне кажется здесь более заметный выигрыш только
в более оптимальном использовании циклов и внутренних проверок
Code (php): скопировать код в буфер обмена
function strhex($string)
{
    $string = (string)$string;
    $len = strlen (www.php.net/strlen)($string);
    $result = "Length: $len\n";

    $dump = $orig = "";
    for ($i = 0; $i < $len; $i++) {
        $char = $string[$i];

        $dump .= sprintf (www.php.net/sprintf)("%02x ", ord (www.php.net/ord)($char));
        $orig .= ($char >= " ") ? $char : ".";

        if ($i && $i % 16 == 15) {
            $result .= "$dump| $orig\n";
            $dump = $orig = "";
        }
    }
    if (strlen (www.php.net/strlen)($orig)) {
        $rem = str_repeat (www.php.net/str_repeat)(" ", 16 - strlen (www.php.net/strlen)($orig));
        $result .= $dump . str_repeat (www.php.net/str_repeat)($rem, 3) . "| $orig$rem\n";
    }
    return $result;
}
Code (any language): скопировать код в буфер обмена
значения = в секундах
1000 символов
strhex  0.0051870346069336
hexDump 0.0074460506439209
hexView 0.0091800689697266

1000000
strhex  10.058950901031
hexDump 11.806213140488
hexView 15.239226818085

2000000
strhex  27.854460000992
hexDump 32.456102132797
hexView 39.256150960922
Back to top
View user's profile Send private message
Юрий Насретдинов
Модератор



Joined: 13 Mar 2003
Posts: 8642
Карма: 198
   поощрить/наказать

Location: 007 495

PostPosted: Mon Aug 15, 2005 10:52 pm (спустя 2 часа 42 минуты; написано за 1 минуту 34 секунды)
   Post subject:
Reply with quote

Rumata
[+], интересная реализация :).
Rumata wrote:
$char >= " "
Хм, это что??? Вообще, фильтрация по char'у хромает - я проверил на архиве DnSearch, там довольно много «ляпов» - символов, которые не отображаются, или которые «вылазят».
Back to top
View user's profile Send private message Send e-mail
Rumata
Профессионал



Joined: 17 Aug 2003
Posts: 1850
Карма: 185
   поощрить/наказать


PostPosted: Mon Aug 15, 2005 11:05 pm (спустя 13 минут; написано за 2 минуты 3 секунды)
   Post subject:
Reply with quote

Юpий Насрeтдинов wrote:
Хм, это что???
что именно смущает? сравнение строк? строка больше другой если она лексикографически больше (то есть ... A < B < C ... a < b < c ...) и содержит больше символов
Back to top
View user's profile Send private message
Юрий Насретдинов
Модератор



Joined: 13 Mar 2003
Posts: 8642
Карма: 198
   поощрить/наказать

Location: 007 495

PostPosted: Mon Aug 15, 2005 11:07 pm (спустя 1 минуту 26 секунд; написано за 12 секунд)
   Post subject:
Reply with quote

Rumata
А почему именно пробел?
Back to top
View user's profile Send private message Send e-mail
Rumata
Профессионал



Joined: 17 Aug 2003
Posts: 1850
Карма: 185
   поощрить/наказать


PostPosted: Mon Aug 15, 2005 11:44 pm (спустя 37 минут; написано за 27 секунд)
   Post subject:
Reply with quote

Юpий Насрeтдинов wrote:
А почему
первый неуправляющий символ
Back to top
View user's profile Send private message
Юрий Насретдинов
Модератор



Joined: 13 Mar 2003
Posts: 8642
Карма: 198
   поощрить/наказать

Location: 007 495

PostPosted: Mon Aug 15, 2005 11:55 pm (спустя 10 минут; написано за 10 секунд)
   Post subject:
Reply with quote

Rumata wrote:
первый неуправляющий символ
Ладно, намёк понял, больше не пристаю ;)
Back to top
View user's profile Send private message Send e-mail
Rumata
Профессионал



Joined: 17 Aug 2003
Posts: 1850
Карма: 185
   поощрить/наказать


PostPosted: Tue Aug 16, 2005 12:33 am (спустя 38 минут; написано за 1 минуту 9 секунд)
   Post subject:
Reply with quote

ascii-table.com/
00-1F - управляющие символы
7F Delete - тоже, но, по-моему, не используется
Back to top
View user's profile Send private message
Юрий Насретдинов
Модератор



Joined: 13 Mar 2003
Posts: 8642
Карма: 198
   поощрить/наказать

Location: 007 495

PostPosted: Tue Aug 16, 2005 1:25 am (спустя 51 минуту; написано за 46 секунд)
   Post subject:
Reply with quote

Rumata
Ну, я нашёл ещё 3 символа, которые не отображаются - с десятеричными кодами 127,152,173, это на самом деле довольно важно - иначе получается неровный hex-дамп в некоторых местах
Back to top
View user's profile Send private message Send e-mail
Rumata
Профессионал



Joined: 17 Aug 2003
Posts: 1850
Карма: 185
   поощрить/наказать


PostPosted: Tue Aug 16, 2005 1:31 am (спустя 5 минут; написано за 1 минуту 57 секунд)
   Post subject:
Reply with quote

7F(Delete) == 127
Юpий Насрeтдинов wrote:
Ну, я нашёл ещё 3 символа
в какой кодировке?
Юpий Насрeтдинов wrote:
неровный hex-дамп
выравнивается стилями. можно добавить в двух местах символ | чтобы показать границу
вообще-то я пока не вижу большой полезности от этой функции. поправь, если не так
Back to top
View user's profile Send private message
Юрий Насретдинов
Модератор



Joined: 13 Mar 2003
Posts: 8642
Карма: 198
   поощрить/наказать

Location: 007 495

PostPosted: Tue Aug 16, 2005 2:35 am (спустя 1 час 4 минуты; написано за 53 секунды)
   Post subject:
Reply with quote

Rumata wrote:
в какой кодировке?
1251
Rumata wrote:
выравнивается стилями.
Неее, там просто какие-то символы чисто браузером не отображаются, так-то нормально всё :)
Rumata wrote:
вообще-то я пока не вижу большой полезности от этой функции.
да, в общем-то, ИМХО тоже никакой пользы от этой функции нету ;)
Back to top
View user's profile Send private message Send e-mail
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 414
   поощрить/наказать


PostPosted: Tue Aug 16, 2005 11:02 pm (спустя 20 часов 27 минут; написано за 36 секунд)
   Post subject:
Reply with quote

Ну вы, блин, даете... :-)
Оптимизируете скорость там, где это, по-моему, совершенно не лимитирует.
Back to top
View user's profile Send private message Send e-mail
Юрий Насретдинов
Модератор



Joined: 13 Mar 2003
Posts: 8642
Карма: 198
   поощрить/наказать

Location: 007 495

PostPosted: Tue Aug 16, 2005 11:22 pm (спустя 20 минут; написано за 31 секунду)
   Post subject:
Reply with quote

Дмитрий Котеров wrote:
Оптимизируете скорость там, где это, по-моему, совершенно не лимитирует.
Да просто, задача не совсем тривиальная :), интересно стало :). Можно даже устроить конкурс - кто напишет функцию, которая делает то же самое быстрее :)
Back to top
View user's profile Send private message Send e-mail
Navigator
Участник форума



Joined: 27 Nov 2004
Posts: 221
Карма: -12
   поощрить/наказать

Location: Павловский Посад

PostPosted: Wed Aug 17, 2005 8:12 am (спустя 8 часов 50 минут; написано за 1 минуту 18 секунд)
   Post subject:
Reply with quote

Юpий Насрeтдинов wrote:
да, в общем-то, ИМХО тоже никакой пользы от этой функции нету ;)
есть. Я, например, пишу icq-бота, а протокол аськи, как исвестно, бинарный. Бот устроен так, что все входящие и исходящие данные пишет в консоль (-:
Юpий Насрeтдинов wrote:
а просто, задача не совсем тривиальная :), интересно стало :). Можно даже устроить конкурс - кто напишет функцию, которая делает то же самое быстрее :)
ну зачем — у меня пакеты максимум весят 1,5 кб (-:
Rumata wrote:
мне кажется здесь более заметный выигрыш только
в более оптимальном использовании циклов и внутренних проверок
скорее всего проверок. Моя ф-я может тормозить из-за preg_replace.
Back to top
View user's profile Send private message
Юрий Насретдинов
Модератор



Joined: 13 Mar 2003
Posts: 8642
Карма: 198
   поощрить/наказать

Location: 007 495

PostPosted: Wed Aug 17, 2005 9:36 pm (спустя 13 часов 24 минуты; написано за 13 секунд)
   Post subject:
Reply with quote

Navigator wrote:
Моя ф-я может тормозить из-за preg_replace.
Вот собственно можно вместо неё использовать другие способы :).
Back to top
View user's profile Send private message Send e-mail
Navigator
Участник форума



Joined: 27 Nov 2004
Posts: 221
Карма: -12
   поощрить/наказать

Location: Павловский Посад

PostPosted: Thu Aug 18, 2005 2:15 pm (спустя 16 часов 38 минут; написано за 1 минуту 20 секунд)
   Post subject:
Reply with quote

Юpий Насрeтдинов, к примеру, то-же самое сравнение с пробелом:
Code (php): скопировать код в буфер обмена
                        $tempRaw .= $tempStr{$j} > " " ? $tempStr{$j} : ".";
Однако лично мне быстродействие по барабану — с большими объёмами данных дела иметь не приходилось… пока (-:


P.S.: не люблю for…
Back to top
View user's profile Send private message
Юрий Насретдинов
Модератор



Joined: 13 Mar 2003
Posts: 8642
Карма: 198
   поощрить/наказать

Location: 007 495

PostPosted: Thu Aug 18, 2005 10:36 pm (спустя 8 часов 21 минуту; написано за 55 секунд)
   Post subject:
Reply with quote

Navigator wrote:
к примеру, то-же самое сравнение с пробелом:
Оно не все символы корректно заменяет, к сожалению. Я уже приводил коды символов в кодировке win1251, которые отображаются некорректно
Navigator wrote:
P.S.: не люблю for…
Зря, кстати, очень мощная конструкция.
Back to top
View user's profile Send private message Send e-mail
Rin
Участник форума



Joined: 01 Jun 2005
Posts: 515
Карма: 185
   поощрить/наказать

Location: Москва

PostPosted: Mon Mar 06, 2006 4:39 pm (спустя 6 месяцев 18 дней 18 часов 2 минуты; написано за 3 минуты 21 секунду)
   Post subject:
Reply with quote

Простой вариант:
Code (php): скопировать код в буфер обмена
<?php

/**
 * Функция, которая выводит HEX представление строки.
 * :NOTE:
 * С оглядкой на MySQL:
 *     mysql> SELECT HEX('abc');
 *            -> 616263
 *
 * @param   string  $s
 * @param   bool    $is_php_code   форматировать как PHP код?
 * @return  string
 *
 * @charset  ANSI
 * @author   Nasibullin Rinat <rin at starlink ru>
 * @version  1.0.0
 */

function hex($s, $is_php_code = false)
{
    return preg_replace_callback (www.php.net/preg_replace_callback)('/./s', create_function (www.php.net/create_function)('$m', 'return ' . ($is_php_code ? '\'\x\' . ' : '') . ' dechex(ord($m[0]));') , $s);
}

#version 2.0
function hex($s, $is_php_code = false, $delim = '')
{
    $r = '';
    for ($i = 0, $c = strlen (www.php.net/strlen)($s); $i < $c; $i++)
    {
        $r .= ($is_php_code ? '\x' : $delim)sprintf (www.php.net/sprintf)('%02x', ord (www.php.net/ord)(substr (www.php.net/substr)($s, $i, 1)));
    }
    return trim (www.php.net/trim)($r);
}

#version 3.0
function hex($s, $is_php_code = false, $delim = '')
{
    return trim (www.php.net/trim)(vsprintf (www.php.net/vsprintf)(str_repeat (www.php.net/str_repeat)(($is_php_code ? '\x' : $delim) . '%02x', strlen (www.php.net/strlen)($s)), unpack (www.php.net/unpack)('C*', $s)), $delim);
}

#version 4.0  (самый быстрый вариант!)
function hex($s, $is_php_code = false, $delim = '')
{
    return trim (www.php.net/trim)(str_replace (www.php.net/str_replace)('-', $is_php_code ? '\x' : $delim, '-' . rtrim (www.php.net/rtrim)(chunk_split (www.php.net/chunk_split)(bin2hex (www.php.net/bin2hex)($s), 2, '-'), '-')), $delim);
}


?>


Last edited by Rin on Thu Mar 09, 2006 11:32 am; edited 3 times in total
Back to top
View user's profile Send private message Send e-mail
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 414
   поощрить/наказать


PostPosted: Mon Mar 06, 2006 5:17 pm (спустя 37 минут; написано за 51 секунду)
   Post subject:
Reply with quote

Ужасно. Вызовете в цикле 1000 раз hex() - получите 1000 созданных анонимных функции, жрущих память. Не говоря уж о тормозах из-за того, что PHP придется каждый раз транслировать код этих функций во внутреннее представление.
Back to top
View user's profile Send private message Send e-mail
Rin
Участник форума



Joined: 01 Jun 2005
Posts: 515
Карма: 185
   поощрить/наказать

Location: Москва

PostPosted: Tue Mar 07, 2006 12:34 pm (спустя 19 часов 16 минут; написано за 4 минуты 34 секунды)
   Post subject:
Reply with quote

Согласен, этот код не претендует ни на скорость, ни на бережное потребление памяти.
Функция написана для отладочных целей. :))

~~~
Написал еще пару вариантов, третий работает в 3 раза быстрее, чем второй.
Жаль, что PHP циклы такие тормозные...
Back to top
View user's profile Send private message Send e-mail
Юрий Насретдинов
Модератор



Joined: 13 Mar 2003
Posts: 8642
Карма: 198
   поощрить/наказать

Location: 007 495

PostPosted: Tue Mar 07, 2006 10:19 pm (спустя 9 часов 45 минут; написано за 40 секунд)
   Post subject:
Reply with quote

Rin
Тогда уж хоть chunk_split добавили, чтоли... А то как для больших файлов выводить... Кстати, попробуйте для больших файликов свою штуку запустить - насколько она будет быстро работать?
Back to top
View user's profile Send private message Send e-mail
Rin
Участник форума



Joined: 01 Jun 2005
Posts: 515
Карма: 185
   поощрить/наказать

Location: Москва

PostPosted: Thu Mar 09, 2006 11:37 am (спустя 1 день 13 часов 17 минут; написано за 1 минуту 40 секунд)
   Post subject:
Reply with quote

Написал 4-й вариант, который работает быстрее, чем третий в 19 раз!
Пригодилась ваша идея использовать chunk_split, но не для конечного форматирования.
Back to top
View user's profile Send private message Send e-mail
Rin
Участник форума



Joined: 01 Jun 2005
Posts: 515
Карма: 185
   поощрить/наказать

Location: Москва

PostPosted: Thu Mar 09, 2006 4:15 pm (спустя 4 часа 38 минут; написано за 2 минуты 50 секунд)
   Post subject:
Reply with quote

Приму участие в вашем соревновании. :)
По скорости идентично strhex() / Rumata.
Code (php): скопировать код в буфер обмена
/*
function hexView($raw, $cols = 16, $alt_char = '.', $is_show_rows = false)
{
    $end_spaces = str_repeat (www.php.net/str_repeat)(' ', ($cols - strlen (www.php.net/strlen)($raw) % $cols) * 3);
    $a = explode (www.php.net/explode)('*', rtrim (www.php.net/rtrim)(chunk_split (www.php.net/chunk_split)(chunk_split (www.php.net/chunk_split)(bin2hex (www.php.net/bin2hex)($raw), 2, ' ') . $end_spaces, $cols * 3, "| *"), '*'));
    foreach (unpack (www.php.net/unpack)('C*', $raw) as $k => $v)
    {
        #
        $a[ceil (www.php.net/ceil)($k / $cols) - 1] .= ($v > 0x7e || $v < 0x20) ? $alt_char : chr (www.php.net/chr)($v);
    }
    if ($is_show_rows)
    {
        $f = '% ' . strlen (www.php.net/strlen)(count (www.php.net/count)($a)) . 'u';
        foreach ($a as $k => $v)
        {
            $a[$k] = sprintf (www.php.net/sprintf)($f, $k) . ' | ' . $v;
        }
    }
    return 'Length: ' . number_format (www.php.net/number_format)(strlen (www.php.net/strlen)($raw)) . " bytes\r\n" . implode (www.php.net/implode)("\r\n", $a) . "\r\n";
}
CHANGELOG:

* 1.0.1 добавлен показ нумерации строк

Last edited by Rin on Fri Mar 10, 2006 11:30 am; edited 2 times in total
Back to top
View user's profile Send private message Send e-mail
ilich
Guest





Карма: 388
   поощрить/наказать


PostPosted: Thu Mar 09, 2006 9:35 pm (спустя 5 часов 19 минут; написано за 2 минуты 8 секунд)
   Post subject:
Reply with quote

Rin wrote:
Code (php): скопировать код в буфер обмена
    include_once 'hex.php';
???
Back to top
Display posts from previous:   
Post new topic   Reply to topic All times are GMT + 3 Hours
Page 1 of 1    Email to a Friend.
You cannot post new topics in this forum. You cannot reply to topics in this forum. You cannot edit your posts in this forum. You cannot delete your posts in this forum. You cannot vote in polls in this forum. You cannot attach files in this forum. You can download files in this forum.
XML