Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.141.32.252] |
|
Сообщ.
#1
,
|
|
|
Привет всем!
Пишу программу для поиска дублей на диске. В ф-ции, приведенной ниже, вылетет ошибка на вызове другой ф-ции. Ошибка "Stream read error", причем вылетает не срузу, первый раз где-то на 10 вызове(примерно), во второй на 36-ом, а в 3-й - на 24-ом. От чего это может быть и как такое лечится? Заренее благодарю. type TFileRecord=record FileName:string[255]; Size:integer end; TFileRecordHash=record FileName:string[255]; Size:integer; Hash:string[16]; end; var FileTable:array of TFileRecord; FileTableHash:array of TFileRecordHash; //пока не используется Duplicates:array of array of TFileRecord; RemoveList:array of char; Canceled:boolean; ........................ procedure FindDuplicates; var i,j:integer; ItemClosed:boolean; ////////////////////////////////// ////Побйтно сравнивает два файла// ////////////////////////////////// function CompFiles(Name1,Name2:string):boolean; var i:integer; Buf1,Buf2:byte; f1,f2:TFileStream; begin try f1:=TFileStream.Create(Name1,fmOpenRead); f2:=TFileStream.Create(Name2,fmOpenRead); for i:=0 to f1.Size do begin f1.ReadBuffer(Buf1,1); f2.ReadBuffer(Buf2,1); if Buf1<>Buf2 then begin result:=false; exit end end; result:=true; finally f1.Free; f2.Free; end end; begin try for i:=0 to Length(FileTable)-1 do if Length(FileTable[i].FileName)<>0 then begin ItemClosed:=true; for j:=0 to Length(FileTable)-1 do if Length(FileTable[j].FileName)<>0 then if i<>j then if FileTable[i].Size=FileTable[j].Size then if CompFiles(FileTable[i].FileName,FileTable[j].FileName) then //Здесь ошибка begin if ItemClosed then begin SetLength(Duplicates,Length(Duplicates)+1); SetLength(Duplicates[Length(Duplicates)-1],{Length(Duplicates[Length(Duplicates)-1])|+}1); Duplicates[Length(Duplicates)-1,0]:=FileTable[i]; ItemClosed:=false end; SetLength(Duplicates[Length(Duplicates)-1],Length(Duplicates[Length(Duplicates)-1])+1); Duplicates[Length(Duplicates)-1,Length(Duplicates[Length(Duplicates)-1])-1]:=FileTable[j]; SetLength(FileTable[j].FileName,0) end; SetLength(FileTable[i].FileName,0) end; finally SetLength(FileTable,0) end end; |
Сообщ.
#2
,
|
|
|
возможно не совпадают размеры файлов. и если уж в цикле от 0, то, имхо до Size-1.
так же возможно имеет смысл использовать не ReadBuffer, а Read, и проверять, что он возвращает корректно прочитанный размер. либо ловить и обрабатывать исключение с пом try..except |
Сообщ.
#3
,
|
|
|
Цитата Alexander N @ for i:=0 to f1.Size do begin f1.ReadBuffer(Buf1,1); f2.ReadBuffer(Buf2,1); if Buf1<>Buf2 then begin result:=false; exit end end; if f1.Size = f2.Size then begin for i:=0 to f1.Size - 1 do begin f1.ReadBuffer(Buf1,1); f2.ReadBuffer(Buf2,1); if Buf1<>Buf2 then begin result:=false; exit end end; end else result := false; |
Сообщ.
#4
,
|
|
|
Мда-а-а, читать файлы по 1 байту это супер
function CompFiles(const Name1,Name2:string):boolean; var FSize,BSize:integer; Buf1,Buf2:array[0..4095] of char; f1,f2:TFileStream; begin Result:=false; f1:=TFileStream.Create(Name1,fmOpenRead); f2:=nil; try f2:=TFileStream.Create(Name2,fmOpenRead); FSize:=f1.Size; if f2.Size <> FSize then Exit; //!!! проверяем равенство размера repeat BSize:=FSize; if BSize > SizeOf(Buf1) then BSize:=SizeOf(Buf1); f1.ReadBuffer(Buf1,BSize); f2.ReadBuffer(Buf2,BSize); if not CompareMem(Buf1,Buf2,BSize) then Exit; dec(FSize,BSize); until FSize <= 0; Result:=true; finally f1.Free; f2.Free; end; end; Добавлено Да и циклы по FileTable ужасно сделаны - нафига гонять второй цикл от 0, когда достаточно от i+1 ?! И куча вложенных if-ов никчему, т.к. можно все в одну строчку написать for i:=0 to Length(FileTable)-1 do if FileTable[i].FileName <> '' then begin ItemClosed:=true; for j:=i+1 to Length(FileTable)-1 do if (FileTable[j].FileName <> '') and (FileTable[i].Size = FileTable[j].Size) and CompFiles(FileTable[i].FileName,FileTable[j].FileName) then begin ... end; end; |
Сообщ.
#5
,
|
|
|
Цитата leo @ RSize:=0; Вроде в объявлении переменных таковой нет.leo, что вы имели в виду? |
Сообщ.
#6
,
|
|
|
Цитата Alexander N @ Вроде в объявлении переменных таковой нет.leo, что вы имели в виду? Эх, на 3 сек. не успел исправить - это не нужно, от другого варианта затесалось... |
Сообщ.
#7
,
|
|
|
Цитата leo @ FSize:=f1.Size; if f2.Size <> FSize then Exit; //!!! проверяем равенство размера А разве нельзя if f1.Size<>f2.Size И вложенные условия нужны для того, чтобы если первое услови не выполняется, не вычислять последующие, т. к. прога должна работать быстро. |
Сообщ.
#8
,
|
|
|
Цитата Alexander N @ А разве нельзя if f1.Size<>f2.Size Можно, только это "не оптимально" , т.к. при при чтении св-ва f1.Size вызывается ф-я АПИ GetFileSize - меня от этих излишеств "коробит" Добавлено Цитата Alexander N @ И вложенные условия нужны для того, чтобы если первое услови не выполняется, не вычислять последующие, т. к. прога должна работать быстро В дельфи и так по умолчанию стоит опция сокращенного вычисления булевских выражений (галка Compleate boolean eval выключена), поэтому как только в цепочке AND встречается false - дальнейшие вычисления прекращаются |
Сообщ.
#9
,
|
|
|
Цитата leo @ Оффтопик, но где эту галку искать. например в d7? галка Compleate boolean eval выключена Добавлено MetalFan, спасибо, с Вашим исправлением прогнал прогу по диску, она больше не слетает(пока ). Цитата Profi @ if f1.Size = f2.Size then begin for i:=0 to f1.Size - 1 do begin f1.ReadBuffer(Buf1,1); f2.ReadBuffer(Buf2,1); if Buf1<>Buf2 then begin result:=false; exit end end; end else result := false; Profi, зчем сравнивать файлы по размеру, если это уже делается до вызова ф-ции, и совпаадение размеров - условие вызова это ф-ции? leo, спасибо за ф-цию сравнения, пока не успел попробовать |
Сообщ.
#10
,
|
|
|
Цитата Alexander N @ Оффтопик, но где эту галку искать. например в d7? Project -> Options -> Compiler -> SyntaxOptions -> Complete boolean eval - по умолчанию выключена, т.е. булевские выражения считаются не полностью, а слево-направо пока не станет ясен результат |
Сообщ.
#11
,
|
|
|
Спасибо!
|
Сообщ.
#12
,
|
|
|
Alexander N, просто не смотрел реализацию второй функции.
|