Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2013.07.21;
Скачать: [xml.tar.bz2];

Вниз

сравнение 2-х TFileStream   Найти похожие ветки 

 
Unknown1   (2012-11-16 11:16) [0]

Как быстро сравнить?


 
RWolf ©   (2012-11-16 11:21) [1]

сравнить размеры, при совпадении прочитать данные поблочно да сравнить, а как ещё-то? потоки ничего больше не умеют, только читать и писать.


 
Unknown1   (2012-11-16 11:34) [2]


> сравнить размеры, при совпадении прочитать данные поблочно
> да сравнить, а как ещё-то? потоки ничего больше не умеют,
>  только читать и писать.


Так вот:


function FilesAreEqual(const FileName1, FileName2: string): Boolean;
const
 BLOCK_SIZE = 65536;
var
 Buf1, Buf2: array[1..BLOCK_SIZE] of Byte;
 FS1, FS2: TFileStream;
 Len1, Len2: Integer;
begin
 Result := False;
 FS1 := TFileStream.Create(FileName1, fmOpenRead or fmShareDenyNone);
 try
   FS2 := TFileStream.Create(FileName2, fmOpenRead or fmShareDenyNone);
   try
     if FS1.Size <> FS2.Size then
       Exit;
     Len1 := FS1.Read(Buf1[1], BLOCK_SIZE);
     Len2 := FS2.Read(Buf2[1], BLOCK_SIZE);
     if Len1 <> Len2 then
       Exit;
     if not CompareMem(@Buf1[1], @Buf2[1], Len1) then
       Exit;
     Result := True;
   finally
     FS2.Free;
   end;
 finally
   FS1.Free;
 end;
end;


 
AV ©   (2012-11-16 11:46) [3]

это первые 65536 байт только


 
Amoeba_   (2012-11-16 11:51) [4]


>  при совпадении прочитать данные поблочно да сравнить, а
> как ещё-то?

Можно и иначе, без TFileStream и без поблочного чтения. Отображаешь файлы (memory mapping, используются ф-и API) в память, и как для двух массивов байтов делаешь CompareMem.


 
RWolf ©   (2012-11-16 11:53) [5]


> Amoeba_   (16.11.12 11:51) [4]

можно, но условием задачи было сравнение 2-х TFileStream.


 
Dimka Maslov ©   (2012-11-16 12:00) [6]

MD5 высчитать для обоих файлов.


 
QAZ9   (2012-11-16 12:50) [7]


> Можно и иначе

можно, но ненужно, ибо будут проблемы как со скоростью, так и с размером файлов


 
bems ©   (2012-11-16 13:26) [8]

С размером только на х32
А какие тут проблемы со скоростью?


 
RWolf ©   (2012-11-16 13:41) [9]

один мой знакомый, помнится, проводил бенчмарк на предмет быстрого подсчёта контрольной суммы больших файлов; у него получалось, что чтение в буфер выигрывает в плане скорости у отображения в память.


 
Игорь Шевченко ©   (2012-11-16 13:52) [10]

RWolf ©   (16.11.12 13:41) [9]

Не выигрывает


 
AV ©   (2012-11-16 15:01) [11]


> Игорь Шевченко ©   (16.11.12 13:52) [10]

почему?

Если файл большой, система скажет, что готово, отображено все. А потом, за кулисами, будет лазить в файл.

против

Зачитать в память все. Если не сбросит в своп - все в память.


 
DVM ©   (2012-11-16 15:09) [12]


class function TStreamHelper.CompareStreams(A, B: TStream;
 BufferSize: Integer = DefStreamBufferSize): Boolean;
var
 BufferA, BufferB: array of Byte;
 ByteCountA, ByteCountB: Longint;
begin
 SetLength(BufferA, BufferSize);
 try
   SetLength(BufferB, BufferSize);
   try
     repeat
       ByteCountA := A.Read(BufferA[0], BufferSize);
       ByteCountB := B.Read(BufferB[0], BufferSize);

       Result := (ByteCountA = ByteCountB);
       Result := Result and CompareMem(BufferA, BufferB, ByteCountA);
     until (ByteCountA <> BufferSize) or (ByteCountB <> BufferSize) or not Result;
   finally
     SetLength(BufferB, 0);
   end;
 finally
   SetLength(BufferA, 0);
 end;
end;


 
DVM ©   (2012-11-16 15:11) [13]


> Можно и иначе, без TFileStream и без поблочного чтения.
> Отображаешь файлы (memory mapping, используются ф-и API)
> в память

Не все можно отобразить в память. Адресное пространстов 32 бит программ невелико по меркам современных жестких дисков и например два видеофайла туда не отобразить больших.


 
Игорь Шевченко ©   (2012-11-16 15:11) [14]


> почему?


почитай как Windows работает с файлами


 
DVM ©   (2012-11-16 15:14) [15]

С чего вдруг сравнение двух файлов отображенных в память будет выигрывать у сравнения двух файлов методом поблочного чтения? При отображении все равно будет такое же чтение с диска такими же блоками, волшебства тут не будет.


 
DVM ©   (2012-11-16 15:14) [16]


> Игорь Шевченко ©   (16.11.12 15:11) [14]

Чтоб сравнить все равно потребуется чтение с диска, как б она с ним не работала.


 
Игорь Шевченко ©   (2012-11-16 15:26) [17]

DVM ©   (16.11.12 15:14) [16]

Почитай, как Windows работает с файлами. Первым делом при чтении в кэш она их отображает в память нужными определенными порциями.


 
DVM ©   (2012-11-16 15:31) [18]


> Игорь Шевченко ©   (16.11.12 15:26) [17]


> Первым делом при чтении в кэш она их отображает в память
> нужными определенными порциями.

Если я буду читать такими же примерно порциями? Сомневаюсь, что будет сильный выигрыш.

Легко поставить эксперимент, кстати. Сейчас проверю.


 
RWolf ©   (2012-11-16 15:33) [19]


> Игорь Шевченко ©   (16.11.12 15:26) [17]

читать в буфер можно ведь и мимо кэша, не?


 
DVM ©   (2012-11-16 15:42) [20]

Сравнил я.
При размере буфера 64к скорости сравнялись. До 64к сравнение отображенных в память было быстрее, чем по блокам. Но тут надо учитывать, что сравнивать все равно придет поблочно читая из отображенных в память файлов, т.к. натравливать на них CompareMem не очень практично, т.к. при больших файлах этот процесс нельзя будет прервать и в реальной жизни так не удобно.


 
DVM ©   (2012-11-16 15:45) [21]

Если отображенные в память файлы сравнивать просто CompareMem, то немного быстрее поблочного чтения, примерно на 25%.


 
Игорь Шевченко ©   (2012-11-16 15:48) [22]

RWolf ©   (16.11.12 15:33) [19]


> читать в буфер можно ведь и мимо кэша, не?


Можно. Но надо исхитряться. По умолчанию работа с файлами выполняется с использованием кэша.


 
Игорь Шевченко ©   (2012-11-16 15:50) [23]

DVM ©   (16.11.12 15:42) [20]

В реальной жизни скорость сравнения двух файлов не так существенна, как кажется. Я делаю тупо, считаю CRC и сравниваю его и размер. Если совпало, то в 99% файлы идентичны.


 
DVM ©   (2012-11-16 15:59) [24]


> Игорь Шевченко ©   (16.11.12 15:50) [23]


> считаю CRC и сравниваю его и размер.

А зачем считать CRC если можно просто побайтно сравнить? CRC же тоже потребует прохода по всем байтам и ее вычислени заведомо медленнее, если речь именно о CRC, а не о Checksum. Имеет смысл, если только один файл многократно надо сравнивать с другими.


 
Игорь Шевченко ©   (2012-11-16 16:03) [25]

DVM ©   (16.11.12 15:59) [24]


> А зачем считать CRC


Я большие группы файлов обрабатываю с целью поиска идентичных. Большие - десятки и сотни тысяч файлов.


 
DVM ©   (2012-11-16 16:06) [26]


> Игорь Шевченко ©   (16.11.12 16:03) [25]


> Я большие группы файлов обрабатываю с целью поиска идентичных

ясно

Кстати я еще погонял тест на разных файлах, очень сильно влияет на результаты кэширование, т.е. фактически делать два раза тест на одних и тех же файлах уже бессмысленно. В среднем быстрее отображенные файлы, да.


 
RWolf ©   (2012-11-16 16:15) [27]


> Я большие группы файлов обрабатываю с целью поиска идентичных.
>  Большие - десятки и сотни тысяч файлов.

опасно при такой обработке полагаться на 32-битный CRC.
есть приличный (1/65536) шанс ложного совпадения.
лучше какую-нибудь хэш-функцию из распространённых.


 
Leonid Troyanovsky ©   (2012-11-16 16:28) [28]


> Unknown1   (16.11.12 11:16)  

> Как быстро сравнить?

http://www.delphimaster.net/view/2-1187943014

--
Regards, LVT.


 
Игорь Шевченко ©   (2012-11-16 16:42) [29]

RWolf ©   (16.11.12 16:15) [27]


> опасно при такой обработке полагаться на 32-битный CRC.


Как выяснилось - не опасно. К тому же я считаю 16-битный CRC


> есть приличный (1/65536) шанс ложного совпадения.


Это при 16-битном, не так ли ?


 
RWolf ©   (2012-11-16 16:44) [30]


> Это при 16-битном, не так ли ?


при 16-битном всё ещё хуже: 1/256.

http://ru.wikipedia.org/wiki/Парадокс_дней_рождения


 
Игорь Шевченко ©   (2012-11-16 16:49) [31]

RWolf ©   (16.11.12 16:44) [30]

Ты невнимательно читаешь.


> считаю CRC и сравниваю его и размер. Если совпало, то в
> 99% файлы идентичны.


 
RWolf ©   (2012-11-16 16:52) [32]


> [31]

да я понял, что размер; просто попадаются наборы файлов одинакового размера — растровые изображения, иконки, карты и т.п., и вот на таких наборах можно поймать коллизию.


 
Игорь Шевченко ©   (2012-11-16 16:55) [33]

RWolf ©   (16.11.12 16:52) [32]

в 99% коллизий не наблюдается. В том числе и среди растровых изображений.


 
QAZ9   (2012-11-16 17:31) [34]


> DVM ©   (16.11.12 16:06) [26]

нет, быстрей буфер если убрать всякие обертки аля "поток"
а чтобы без учета кэша тестить - перезагрузи комп :)


 
QAZ9   (2012-11-16 17:37) [35]

заодно дефрегментацию этих файлов сделай


 
DVM ©   (2012-11-16 18:17) [36]


> QAZ9   (16.11.12 17:31) [34]
>
> > DVM ©   (16.11.12 16:06) [26]
>
> нет, быстрей буфер если убрать всякие обертки аля "поток"

обертки практически не ухудшают результат, если не по одному байту читать


 
QAZ9   (2012-11-16 20:16) [37]


> обертки практически

ну как сказать :) иногда катастрофически ухудшают
лично я тестил с результатом в пользу буфера + у него есть некоторые плюсы которые с первого взгляда не бросаются в глаза
а вот функции меморимапеда даже некоректно переведены в самой дельфе (7й версии например)


 
Inovet ©   (2012-11-16 20:45) [38]

> [37] QAZ9   (16.11.12 20:16)
> а вот функции меморимапеда даже некоректно переведены в
> самой дельфе (7й версии например)

Куда переведены заголовки что ли? И что, по этой причине запрещается пользоваться отображением файлов на память?


 
bems ©   (2012-11-16 21:08) [39]


> почему?
>
> Если файл большой, система скажет, что готово, отображено
> все. А потом, за кулисами, будет лазить в файл.
>
> против
>
> Зачитать в память все. Если не сбросит в своп - все в память.
>
в такой постановке они равны, а чтение в буффер не лучше


> Но тут надо учитывать, что сравнивать все равно придет поблочно
> читая из отображенных в память файлов, т.к. натравливать
> на них CompareMem не очень практично, т.к. при больших файлах
> этот процесс нельзя будет прервать и в реальной жизни так
> не удобно.

весь замапленный файл уже считай буффером и читать оттуда поблочно не придётся. А если нужно прервать то можно или или написать свою функцию сравнения, или вызывать CompareMem поблочно, но при этом блоки не копировать лишний раз


 
DVM ©   (2012-11-17 00:17) [40]


> bems ©   (16.11.12 21:08) [39]


>  или вызывать CompareMem поблочно, но при этом блоки не
> копировать лишний раз

Вот если так делать, то отличия с поблочным чтением прямо из файлов с диска становятся не очень заметны. Наибольший выигрыш удалось получить, если CompareMem натравливать на целиком буфера. Но этот способ имеет недостатки.

Вообще со всем этим отображением на 32 бит системах проблем может быть больше чем кажется. Если память процесса представляет собой решето из занятых и свободных блоков, а это очень может получиться так, если в процессе работы он часто что-то будет отображать в память и параллельно выделять память для своих нужд, то спроецировать туда что-то значительное не выйдет.



Страницы: 1 2 3 вся ветка

Форум: "Начинающим";
Текущий архив: 2013.07.21;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.56 MB
Время: 0.005 c
11-1246891762
Galkov
2009-07-06 18:49
2013.07.21
Про дружбу KOL и FPC


2-1353504016
Tcount
2012-11-21 17:20
2013.07.21
Пишу свое интернет-радио...


3-1291201543
StriderMan
2010-12-01 14:05
2013.07.21
isc_shutinprog


3-1286827107
well
2010-10-11 23:58
2013.07.21
Как удалить(заменить) сообщение об удалении записи?


15-1362232290
Kerk
2013-03-02 17:51
2013.07.21
LISPообразное нечто





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский