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

Вниз

Сравнение двух файлов, очень медленно!   Найти похожие ветки 

 
SHS   (2004-01-06 13:31) [0]

Сравниваю побайтно два файла и если есть различия, вывожу их в ListView, но это происходит очень медленно, как можно добиться максимальной производительности? Вот полная процедура сравнения:

procedure TfmMain.btCompareClick(Sender: TObject);
var
hFile: THandle;
File1, File2: file;
Byte1, Byte2: byte;
FSize, i: integer;
begin
if not (FileExists(Edit1.Text) and FileExists(Edit2.Text)) then
begin
MessageBoxA(Handle, "Please, select file to compare", "Error", MB_ICONSTOP);
Exit;
end;

fmMain.Cursor := crHourGlass;

hFile := CreateFile(PChar(Edit1.Text), 0, FILE_SHARE_READ,nil,OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE,0);
if hFile = INVALID_HANDLE_VALUE then
Exit;
FSize := GetFileSize(hFile, nil);

AssignFile(File1, Edit1.Text);
AssignFile(File2, Edit2.Text);
Reset(File1, 1);
Reset(File2, 1);

for i := 0 to FSize - 1 do
begin
Seek(File1, i);
Seek(File2, i);
BlockRead(File1, Byte1, 1);
BlockRead(File2, Byte2, 1);
if Byte1 <> Byte2 then
begin
with ListView.Items.Add do
begin
Caption:=IntToHex(i, 8);
SubItems.Add(IntToHex(Byte1, 2));
SubItems.Add(IntToHex(Byte2, 2));
end;
end;
Application.ProcessMessages;
end;

CloseFile(File1);
CloseFile(File2);

fmMain.Cursor := crDefault;
end;


 
alex_***   (2004-01-06 13:35) [1]

считывать буфером, скажем по 4к, копить текстовую инфу и выкидывать ее через какое-то кол-во шагов или после сравнения.


 
Sandman25   (2004-01-06 13:35) [2]

Лучше считывать и сравнивать не по одному байту.


 
Тимохов   (2004-01-06 13:36) [3]

Можно файлы считывать в память целиком и сравнивать уже там также побайтно.


 
SHS   (2004-01-06 13:37) [4]

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


 
Sandman25   (2004-01-06 13:39) [5]

[4] SHS (06.01.04 13:37)

Сравнив данный кусок еще раз, побайтно :)


 
SHS   (2004-01-06 13:41) [6]

Как считывать в память целиком, MapViewOfFile?


 
Sha   (2004-01-06 13:41) [7]

Считывать блоками (по 64к), сравнивать словами (тип cardinal или integer)


 
alex_***   (2004-01-06 13:42) [8]

mem := TMemoryStream.Create();
mem.LoadFromFile(...);


 
Тимохов   (2004-01-06 13:43) [9]

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

Определите длину файла.
Память берите через getmem.
Закачивайту сразу все. Не забудте BlockRead(File, P ^,...)
Сравнивайте в памяти.
Удаляйте freemem.

Все.


 
alex_***   (2004-01-06 13:43) [10]

Надо вам с казать, господа, что основные тормоза, скорее всего, не из-за алгоритма сравнения, а из-за вывода в ListView после каждого байта.


 
Sha   (2004-01-06 13:44) [11]

И убери все связанное с hFile


 
Тимохов   (2004-01-06 13:44) [12]

alex_*** © (06.01.04 13:42) [8]
Лучший метод.
Но если все-таки делать BlockRead, то можно большему научиться, если конечно самообразование входит в ваши задачи.


 
Sha   (2004-01-06 13:45) [13]

alex_*** © (06.01.04 13:43) [10]
И это тоже


 
Sandman25   (2004-01-06 13:45) [14]

[10] alex_*** © (06.01.04 13:43)

Тогда можно еще добавить LockWindowUpdate


 
SHS   (2004-01-06 13:47) [15]

Спасибо ВСЕМ большое за советы, буду пробовать, правда пока слабо во в этом разбираюсь :)


 
Sha   (2004-01-06 13:49) [16]

Seek(File1, i);
Seek(File2, i);
Application.ProcessMessages;


Это тоже лишнее


 
SHS   (2004-01-06 13:59) [17]

To alex_*** ©: В моём случае тормоза не из-за ListView, а в том, как я организовал сравнение, даже если файлы идентичны - всё это долго происходит.

To Sha ©: Убрал как вы подсказали, спасибо, но надо, видимо, ещё в сторону BlockRead идти, большими блоками считывать что ли...


 
raidan   (2004-01-06 14:02) [18]

Нда...
Где мои пятнадцать лет, где мои пятнадцать лет...


 
raidan   (2004-01-06 14:10) [19]

var f1,f2:file;
buffer1,buffer2:array[1..48*1024]of byte;
res1,res2:integer;
i:integer;
pos:integer;

<...........>

assignfile(f1,edit1.text);
assignfile(f2,edit2.text);
if filesize(f1)<>filesize(f2) then begin
//материться, что файлы не равны
exit;
end;
reset(f1,1);
reset(f2,1);
{$R-}
repeat
pos:=filepos(f1);
blockread(f1,buffer1,48*1024,res1);
blockread(f2,buffer2,48*1024,res2);

for i:=1 to res1 do begin
if buffer1[i]<>buffer2[i] then begin
//материться, что файлы не равны
//в байте pos+i-1, байт buffer1[pos+i-1] не равен buffer2[pos+i-1]
closefile(f2);
closefile(f1);
exit;
end;
end;

application.ProcessMessages;
until (res1=0) or (res2=0) or (res1<>res2);

closefile(f2);
closefile(f1);


 
raidan   (2004-01-06 14:11) [20]

Лениво писать лучший вариант с нормальными проверками и т.д. и т.п. :(


 
YuRock   (2004-01-06 14:23) [21]

> Тимохов © (06.01.04 13:43) [9]

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


Интересно, а что будет, если файл, скажем, 3Гб? Ведь макс. кол-во памяти, которую может использовать программа - 2Гб!

Надо буффер делать! Килобайт по 20, например...


 
Sha   (2004-01-06 14:32) [22]

raidan © (06.01.04 14:10) [19]
"To use FileSize, the file must be open."


 
SHS   (2004-01-06 14:35) [23]

To raidan ©: Лучший вариант и не надо, с остальным я уже сам разберусь :) Работает - супер, скорость вообще обалденная, на то, что раньше выполнялось несколько секунд, уходят какие-то доли секунды! Поверить не могу :) Огромное спасибо за конкретный пример, очень благодарен. И спасибо ещё раз ВСЕМ, кто потратил время на разъяснение мне этого вопроса.


 
Тимохов   (2004-01-06 14:58) [24]

YuRock © (06.01.04 14:23) [21]
Ну уж знаете ли, тогда ответьте на вопрос, что будет если еть всего 1мб, но отличие в каждом байте? Не гикнется ли ListView?


 
Sandman25   (2004-01-06 16:03) [25]

[24] Тимохов © (06.01.04 14:58)

Не ссорьтесь. Умная программа запросит размер файла, узнает, сколько памяти может ей выделить Windows и выберет наилучший алгоритм работы :)


 
ЮрийК   (2004-01-06 16:56) [26]

Лучше всего MapViewOfFile, думаю. Маппируешь два файла целиком и сравниваешь хоть побайтно, хоть словами или двойными словами даже.


 
alex_***   (2004-01-06 17:12) [27]

для сравнения, я думаю, можно использовать CompareString(...). Там сделано оптимально, я надеюсь.


 
raidan   (2004-01-06 17:33) [28]


> Sha © (06.01.04 14:32) [22]
"To use FileSize, the file must be open."

Вполне быть может :)
Я еще не настолько крут, чтобы писать по-памяти без ошибок :)))



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

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

Наверх




Память: 0.5 MB
Время: 0.011 c
14-63396
Igor_thief
2003-12-28 15:14
2004.01.20
Currency


3-62979
kostyan
2003-12-24 09:21
2004.01.20
SharedStream


8-63268
JohnJ
2003-09-18 10:21
2004.01.20
динамик


14-63357
sync
2003-12-29 22:05
2004.01.20
Помогите разобраться с протаколами


1-63225
Mr. Chel
2004-01-09 12:55
2004.01.20
Объекты на форме VS мышь.





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский