Привет всем
Цель - читаем файл и создаем для него уникальный хеш, что бы можно было даже в случае переименования получить такой же хеш.
Уже есть такие утилитки как md5sum, shaXXXsum ...
но проблема в том что файл на 4Гб у меня для md5sum отдает хеш за ~3m, sha1sum за ~5m
А Мне нужно очень быстро. Планируется получать хеши для видео файлов, образов дисков и т.д. Размер от 1Мб до 16Гб. Использование md5sum и т.д. - очень долго, мне бы что-то что читало бы несколько мелких частей (от 128Кб до 1Мб каждая например) файла из начала середины конца и конца например что то типа:
./supercat file.avi| md5sumПомогите ПЛЗ
Можно сделать то, что вы хотите -- посчитать хеш только по некоторым блокам. Но тогда хеш не будет уникальным. Допустим у вас есть файл:XXXXXAAAAAAAAAAAAAAAAAXXXXXXAAAAAAAAAAAAAAAAXXXXXX
Буквами X обозначены те блоки, которые включены в хеш. Тогда те блоки, которые обозначены буквой A можно произвольно менять, и хеш не изменится.
Так что этот метод не подходит не только для криптогафических применений, но и для отслеживания изменений файлов. Для глобальной идентификации файлов по всему миру он тоже не подходит. Тут лучше посмотрите в строну хешей в сети edonkey. Большой плюс -- они уже посчитаны для миллионов файлов и подходят не только для "идентификации"... =)
А вот если вы просто хотите создать некоторую маленькую строку, которой потом будете идентифицировать файл локально -- например, при добавлении файла в фильмотеку для него создаётся такой хеш, который служет идентификатором каким-то -- ваша схема вполне подходит. Только тут лучше не изобретать велосипед, и использовать UUID, потому что для работы с ним уже много готовых библиотек есть. Да и сам UUID более стандартная вещь, чем такой самопальный хеш.
Если вы таки хотите хеш по всему файлу, то учитывайте, что время его подсчёта будет как минимум равно времени чтения файла. Поэтому замерьте cat file > /dev/null для начала. Это и будет минимально достижимое время *в принципе*.
>[оверквотинг удален]
>
>Буквами X обозначены те блоки, которые включены в хеш. Тогда те
>блоки, которые обозначены буквой A можно произвольно менять, и хеш не
>изменится.
>
>Так что этот метод не подходит не только для криптогафических применений, но
>и для отслеживания изменений файлов. Для глобальной идентификации файлов по
>всему миру он тоже не подходит. Тут лучше посмотрите в
>строну хешей в сети edonkey. Большой плюс -- они уже
>посчитаны для миллионов файлов и подходят не только для "идентификации"... =)Во первых - Я максимум буду иметь 1-100млн файлов для которых хеш должен различатся.
Во вторых Я хочу читать из файлов в 5-25-ти(n) местах одинаковое количество Кб. Допустим из файла размером 100Мб Я прочитаю 25*128Кб непрерывным потоком и отправлю на mdsum - который и посчитает хеш... Алгоритм такой - берём размер файла, делим на сколько блоков читать(n), читаем n блоков а размер блока(r) будет опредёлён так - если размер файла/n >1M читаем r=1М, всё остальное - r =размер файла/(2*n), если размер файла <N байт - читаем весь файл...>А вот если вы просто хотите создать некоторую маленькую строку, которой потом
>будете идентифицировать файл локально -- например, при добавлении файла в фильмотеку
>для него создаётся такой хеш, который служет идентификатором каким-то -- ваша
>схема вполне подходит. Только тут лучше не изобретать велосипед, и
>использовать UUID, потому что для работы с ним уже много готовых
>библиотек есть. Да и сам UUID более стандартная вещь, чем
>такой самопальный хеш.Да - локальное применение
Не понял из манов по UUID -может ли она на основании фала выдавать данные...>Если вы таки хотите хеш по всему файлу, то учитывайте, что время его подсчёта будет как минимум равно времени чтения файла. Поэтому замерьте cat file > /dev/null для начала. Это и будет минимально достижимое время *в принципе*.
нет. Про cat - понял, тут наверное и запираются md5sum &etc
>Во первых - Я максимум буду иметь 1-100млн файлов для которых хеш
>должен различатся.С вашей схемой можно элементарно создать два файла, для которых хеш будет одинаковый, миллионов файлов для этого не нужно.
>Да - локальное применение
>Не понял из манов по UUID -может ли она на основании фала
>выдавать данные...Да, генерируется просто случайная, уникальная последовательность. А зачем вам на основе данных файла? У вас ведь задача не создать хеш, отражающий содержимое *всего* файла (иначе бы вы не задали вопрос), а просто создать некоторую уникальную последовательность символов, которую вы будете ассоциировать со своим файлом. Именно для этого и придуман UUID. Приведите, пожалуйста, конкретные примеры применения того хеша, который вы хотите сделать.
>>Если вы таки хотите хеш по всему файлу, то учитывайте, что время его подсчёта будет как минимум равно времени чтения файла. Поэтому замерьте cat file > /dev/null для начала. Это и будет минимально достижимое время *в принципе*.
>
>нет. Про cat - понял, тут наверное и запираются md5sum &etcА давайте не гадать на кофейной гуще, а оперировать цифрами:
/usr/bin/time -v cat file > /dev/null
/usr/bin/time -v md5sum file
>>Во первых - Я максимум буду иметь 1-100млн файлов для которых хеш
>>должен различатся.
>
>С вашей схемой можно элементарно создать два файла, для которых хеш будет
>одинаковый, миллионов файлов для этого не нужно.Отвечаю ниже
>>Да - локальное применение
>>Не понял из манов по UUID -может ли она на основании фала
>>выдавать данные...
>
>Да, генерируется просто случайная, уникальная последовательность. А зачем вам на основе
>данных файла? У вас ведь задача не создать хеш, отражающий
>содержимое *всего* файла (иначе бы вы не задали вопрос), а просто
>создать некоторую уникальную последовательность символов, которую вы будете ассоциировать со своим
>файлом. Именно для этого и придуман UUID. Приведите, пожалуйста,
>конкретные примеры применения того хеша, который вы хотите сделать.Мне нужен хеш, который Я буду получать на основании файла и что бы он был всегда одинаковый даже если переименовать файл!!!
Я уже писал, что Мне бы подошло использование - md5sum, но хеш строится как Я понимаю _для_всего_файла_ а значит что это очень долго. Я писал что замерял для 4Гб файла это порядка 2минут, Я же хочу не больше 5-ти секунд.
Во первых контент у Меня - музыка, фильмы, архивы, образы.
Как определить что файл уникален?
Во первых размер - даже если возьмем фильм, отрежим от него кусок то размер будет различен.
Во вторых какая вероятность что взятые 25 частей файла по n байт будут похожи и при этом размер у них будет одинаковый?
Для ускорения обсчета этого хеша Я хочу написать утилку наподобии cat, которая будет читать несколько частей файла и выводить их непрерывным потоком а в конце или в начале в вывод добавлять размер файла.>>>Если вы таки хотите хеш по всему файлу, то учитывайте, что время его подсчёта будет как минимум равно времени чтения файла. Поэтому замерьте cat file > /dev/null для начала. Это и будет минимально достижимое время *в принципе*.
>>
>>нет. Про cat - понял, тут наверное и запираются md5sum &etc
>
>А давайте не гадать на кофейной гуще, а оперировать цифрами:
>
>/usr/bin/time -v cat file > /dev/null
>/usr/bin/time -v md5sum fileВ том то и дело что не хочу по всему файлу
>Во вторых какая вероятность что взятые 25 частей файла по n
>байт будут похожи и при этом размер у них будет одинаковый?Вероятность близка к нулю, но всё же не ноль. В принципе, для ваших целей этот метод может и подходит, но криптографической строгости тут нет.
>Для ускорения обсчета этого хеша Я хочу написать утилку наподобии cat, которая
>будет читать несколько частей файла и выводить их непрерывным потоком а
>в конце или в начале в вывод добавлять размер файла.Вполне. Можете обсчитать первый и последний мегабайт. Приблизительно так:
#!/usr/bin/perluse warnings;
use strict;use Fcntl qw(SEEK_END);
use Digest::MD5;our $file = $ARGV[0];
if(! -f $file)
{
die("not a regular file");
}my $size = (stat($file))[7];
my $ctx = Digest::MD5->new();
my $buf = '';
open(FILE, '<', $file) or die("can't open file");
read(FILE, $buf, 1024*1024);
$ctx->add($buf);if($size >= 1024*1024*2)
{
seek(FILE, 1024*1024, SEEK_END);
read(FILE, $buf, 1024*1024);
$ctx->add($buf);
}
close(FILE);print($ctx->hexdigest, "\n");
Спасибо
Поможете с файлами <2Mbdom /my/ISO# time ./cat debian-40r1-i386-DVD-1.iso
c7d4f349f17fd5fd3c9d9857258e6ecfreal 0m0.056s
user 0m0.037s
sys 0m0.015s
dom /my/ISO# time md5sum debian-40r1-i386-DVD-1.iso
119abda7c941135d5bf382c386bca2ca debian-40r1-i386-DVD-1.isoreal 4m26.976s
user 0m22.703s
sys 0m8.507s
>Спасибо
>Поможете с файлами <2MbВ том скрипте ситуация файл <2Mb тоже обрабатывается. В этом случае обсчитывается только первый мегабайт.
>>Спасибо
>>Поможете с файлами <2Mb
>
>В том скрипте ситуация файл <2Mb тоже обрабатывается. В этом случае
>обсчитывается только первый мегабайт.Может кто поможет на php этот скрипт перевести?
Я для Перла и ПХП разные данные получаю и Мне кажется ПХП неправильно отрабатывает.#!/usr/bin/php
<?php
$file="Fedora-8-i386-DVD.iso";
if(is_file($file))
{
$handle=fopen($file,"r");
$sizebyte=sprintf("%u", filesize($file));if($sizebyte<1024*1024*2)
{
$md=md5(fread($handle,filesize($file)));
}if($sizebyte>=1024*1024*2)
{
$md=md5(fread($handle,1024*1024)+fseek($handle,1024*1024,SEEK_END));
}
echo "\n".$md."\n";}
?>
>Может кто поможет на php этот скрипт перевести?
>Я для Перла и ПХП разные данные получаю и Мне кажется ПХП
>неправильно отрабатывает.
>Вот поправил вроде:
#!/usr/bin/php
<?php
$file="Fedora-8-i386-DVD.iso";
if(is_file($file))
{
$handle=fopen($file,"r");
$sizebyte=sprintf("%u", filesize($file));if($sizebyte<1024*1024*2)
$md=md5(fread($handle,filesize($file)));if($sizebyte>=1024*1024*2)
{
$m=fread($handle,1024*1024);
fseek($handle,-1024*1024,SEEK_END);
$m .=fread($handle,1024*1024);
$md=md5($m);
}echo "\n".$md."\n";
fclose($handle);
}
?>
Вот только ещё бы if(){} else {} использовать, и имена понятные переменным дать. Дался вам этот PHP... Нормальным языкам такие хаки не нужны:
$sizebyte=sprintf("%u", filesize($file));$m -> $data
$md -> $hash
>Вот только ещё бы if(){} else {} использовать, и имена понятные переменным
>дать. Дался вам этот PHP... Нормальным языкам такие хаки
>не нужны:
>$sizebyte=sprintf("%u", filesize($file));
>$m -> $data
>$md -> $hash+1 - Я пока нашел и вообще это хорошо что нашел :)
Но проблема в том что:
а - для перла Я еще не созрел
б - проект который Я делаю на ПХП и Мне хочется как можно меньше костылей со стороны. Тоесть Я не хотел бы использовать для написания и С/С++ и перл и пхп и сторонии утилиты вызывать вызовами :)
в - Я пока не добился того что бы тот хеш который Я получаю на ПХП соответствовал тому что выдает Перл, а значит Я не могу использовать и Перл и ПХП -только что-то одно.
Еще Мне нужен алгорит обхода всех директорий, поторые лежат в даной директории.
Заранее благодарен.#!/usr/bin/php
<?php
$file="Fedora-8-i386-DVD.iso";
if(is_file($file))
{
$handle=fopen($file,"r");
$sizebyte=sprintf("%u", filesize($file));if($sizebyte<1024*1024*2)
{
$mdhash=md5(fread($handle,filesize($file)));
}
else
{
$hash=fread($handle,1024*1024);
fseek($handle,-1024*1024,SEEK_END);
$hash .=fread($handle,1024*1024);
$mdhash=md5($hash);
}
fclose($handle);
echo "\n hash is == ".$mdhash."\n";
}
else
{
echo "-not-is-file-";
}
?>
> в - Я пока не добился того что бы тот хеш
>который Я получаю на ПХП соответствовал тому что выдает Перл, а
>значит Я не могу использовать и Перл и ПХП -только
>что-то одно.Только что проверил -- тот скрипт на PHP, что в вашем сообщении и мой скрипт на Perl выдают одинаковые результаты. По крайней мере, на файле размером 1.6Gb, больше я у себя не нашёл.
> Еще Мне нужен алгорит обхода всех директорий, поторые лежат в даной
>директории.Ничего сложного. (В Perl для этого вообще есть специальный пакет) Проще всего написать рекурсивную функцию, которая делает следующее:
opendir()
readdir() и для каждого файла:
если файл -- выполняет ваш код
если каталог -- шаг рекусрии
Почитайте http://php.net/readdir там наверное даже готовый код есть
> Еще Мне нужен алгорит обхода всех директорий, поторые лежат в даной
>директории.
>Заранее благодарен.http://pear.php.net/package/HTML_TreeMenu
То что нужно, файл map_fs.php
Можно попробовать поиграться с head/tail, которым можно указать количество байт для чтения.
>[оверквотинг удален]
>но проблема в том что файл на 4Гб у меня для md5sum
>отдает хеш за ~3m, sha1sum за ~5m
>А Мне нужно очень быстро. Планируется получать хеши для видео файлов, образов
>дисков и т.д. Размер от 1Мб до 16Гб. Использование md5sum и
>т.д. - очень долго, мне бы что-то что читало бы несколько
>мелких частей (от 128Кб до 1Мб каждая например) файла из начала
>середины конца и конца например что то типа:
>./supercat file.avi| md5sum
>
>Помогите ПЛЗНапример, для видео файла достаточно создать хэш заголовка, не обязательно генерировать его по всем данным. В заголовке содержится детальная информация о потоках и если хэши и совпали, то скорее всего это тот-же фильм. Плюс включать в хэш размер файла.