Форум: "Основная";
Текущий архив: 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