Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2007.08.05;
Скачать: CL | DM;

Вниз

Ошибка в FileSize   Найти похожие ветки 

 
MTsv DN ©   (2006-12-21 22:55) [0]

Вот тестовый проект:
program test;

uses KOL;

var
Form, Edit, Button : PControl;

procedure OnClick_( Dummy : Pointer; Sender: PControl);
var
F : File;
Buf : array [0..511] of Byte;
i : integer;
begin
Button.Enabled := false;
Assign(F, "tmp.tmp");
Rewrite(F, 1);
for i := 0 to 1000 do
 BlockWrite(F, Buf, 512);
CloseFile(F);
Button.Enabled := true;
if FileSize("tmp.tmp") < 1000000 then
 Edit.Text := "tmp.tmp";
end;

begin
Form := NewForm(nil, "").SetSize(200, 80);
Form.CenterOnParent;
Edit := NewEditBox(Form, []).SetAlign(caTop);
Button := NewButton(Form, "Click").SetAlign(caBottom);
Button.OnClick := TOnEvent(MakeMethod(nil, @OnClick_));
Run(Form);
end.


Результат этой строчки в KOL.PAS:
 Result := {$IFDEF _D2orD3} FD.nFileSizeLow
           {$ELSE} PInt64( @ FD.nFileSizeLow )^ {$ENDIF};

Result := 72339446972273152

Почему бы не вернуться к коду:
function FileSize( const Path: KOLString ) : {$IFDEF _D2orD3} Integer {$ELSE} Int64 {$ENDIF};
var FD : TFindFileData;
   HiSize : {$IFDEF _D2orD3} Integer {$ELSE} Int64 {$ENDIF};
begin
 Result := 0;
 if not Find_First( Path, FD ) then exit;
 Result := FD.nFileSizeLow;
{$IFNDEF _D2orD3}
  if ((FD.nFileSizeLow and $80000000) <> 0) or
    (FD.nFileSizeHigh <> 0) then
  begin
   HiSize := FD.nFileSizeHigh * MAXDWORD;
   Result := HiSize + FD.nFileSizeLow;
  end;
{$ENDIF}
 Find_Close( FD );
end;

Он также учитывает файлы БОЛЬШИХ РАЗМЕРОВ.


 
Galkov ©   (2006-12-22 00:21) [1]

Конечно бага... У Билла тоже - ума палата. Это надо же было старшее слово раньше поставить...

Хитрые умножения против 2-х mov-ов это перебор, конечно...
Что-нибудь такого типа надо:

type T = record L,H:DWORD end;
..........
 T(Result).L := FD.nFileSizeLow;
 T(Result).H := FD.nFileSizeHigh;


 
Galkov ©   (2006-12-22 09:02) [2]


> Он также учитывает файлы БОЛЬШИХ РАЗМЕРОВ.

Учитывает. Только правильно ли :)))


 
MTsv DN ©   (2006-12-22 10:00) [3]

> Учитывает. Только правильно ли :)))
Понял что намек, но не понял на что :)
Вот из MSDN про это:
nFileSizeHigh

Specifies the high-order DWORD value of the file size, in bytes. This value is zero unless the file size is greater than MAXDWORD. The size of the file is equal to (nFileSizeHigh * MAXDWORD) + nFileSizeLow.

nFileSizeLow

Specifies the low-order DWORD value of the file size, in bytes.

А на две операции разбил, т.к. когда тестил получалось типа косяка в [0]


 
Galkov ©   (2006-12-22 11:22) [4]

1) Откуда известно, что призведение двух dword-ов будет int64 ??? Народ против таких приколов всякие MulDiv-ы изобретал....
2) Приведенная ф-ла соответствует действительности в случае MAXDWORD=$100000000. Данная MSDN-нарезка из раздела Platform Builder for Microsoft Windows CE 5.0
Не знаю чему там равно MAXDWORD, но в дельфях вроде $FFFFFFFF
3) Мало ли чего на заборе пишут....

Тестировать лично у меня не получалось: мой самый большой файл, это на локалке нашел MSDN.rar - всего 1.7Г
Но когда народ спрашивал, я им выкинул такой fix, и получил радостные сообщения о соответствии показаний с другими ф.менеджерами

function FileSize( const Path : String ) : Int64;
type T = record L,H:DWORD end;
var FD : TWin32FindData;
   FH : THandle;
begin
 FH := FindFirstFile( PChar( Path ), FD );
 Result := 0;
 if FH = INVALID_HANDLE_VALUE then exit;
 T(Result).L := FD.nFileSizeLow;
 T(Result).H := FD.nFileSizeHigh;
 FindClose( FH );
end;


 
Galkov ©   (2006-12-22 12:08) [5]

btw: В том же MSDN (но чуток в другом под-разделе) есть такое:

nFileSizeHigh
High-order DWORD value of the file size, in bytes. This value is zero unless the file size is greater than MAXDWORD. The size of the file is equal to (nFileSizeHigh * MAXDWORD+1) + nFileSizeLow.

nFileSizeLow
Low-order DWORD value of the file size, in bytes.


Думается, что здесь адекватнее говорить не о потерянной паре скобок, а о заборе
У меня MSDN April 2005   :)))))


 
Galkov ©   (2006-12-22 12:47) [6]

Мда... Воды не мало утекло, с тех пор как я разбил стекло :))
В сегодняшнем KOL это уже надо делать так, оказывается:

function FileSize( const Path: KOLString ) : {$IFDEF _D2orD3} Integer {$ELSE} Int64 {$ENDIF};
var FD : TFindFileData;
begin
 Result := 0;
 if not Find_First( Path, FD ) then exit;
 T(Result).L := FD.nFileSizeLow;
 {$IFNDEF _D2orD3}T(Result).H := FD.nFileSizeHigh;{$ENDIF}
 Find_Close( FD );
end;


 
MTsv DN ©   (2006-12-22 12:50) [7]

> 2) Приведенная ф-ла соответствует действительности в случае MAXDWORD=$100000000. Данная MSDN-нарезка из раздела Platform Builder for Microsoft Windows CE 5.0 Не знаю чему там равно MAXDWORD, но в дельфях вроде $FFFFFFFF
MAXDWORD := 4294967295 Причем тут 1.7ГБ???

> Тестировать лично у меня не получалось: мой самый большой
> файл, это на локалке нашел MSDN.rar - всего 1.7Г

Под БОЛЬШИМ ФАЙЛОМ, я имел ввиду размером большим 4ГБ, т.е. максимально разрешенного на FAT32. 1.7ГБ и так правильно в nFileSizeLow получается, а вот бОльший размер равен как раз (nFileSizeHigh * MAXDWORD) + nFileSizeLow

P.S. Все равно не понимаю, чем Вас код в [0] не устраивает... Я его тестировал на файлах 5 и 7 ГБ... Все правильно возвращает...
Хотя это не принципиально уже...я тему начинал из-за того, что текущая версия FileSize выдает ошибку, а какую реализацию возьмет Владимир неважно, главное, чтобы работало без "косяков"...


 
Galkov ©   (2006-12-22 13:03) [8]


> Причем тут 1.7ГБ???

Тестировать мне нечем, чтобы сказать мог: ПРОВЕРИЛ, И РАБОТАЕТ ПРАВИЛЬНО, ДО ПОСЛЕДНЕГО БАЙТА. Сейчас могу только на других ссылаться.
И больше не причем.


> бОльший размер равен как раз (nFileSizeHigh * MAXDWORD) + nFileSizeLow


Не равен. Не зависимо ни от чьего мнения.
Арифметика - наука точная.
Равен может быть только в таком случае:
nFileSizeHigh * (MAXDWORD+int64(1)) + nFileSizeLow


 
MTsv DN ©   (2006-12-22 13:30) [9]

> Не равен. Не зависимо ни от чьего мнения.
> Арифметика - наука точная.
> Равен может быть только в таком случае:
> nFileSizeHigh * (MAXDWORD+int64(1)) + nFileSizeLow

Совсем плохой стал...сорри...в [5] +1 не увидил. Да, здесь Вы правы!!!


 
Galkov ©   (2006-12-22 18:31) [10]

Смеха ради нашел в MSDN еще одну (третью - одну давали Вы, и она там есть, я вторую выше), но уже правильную формулу :)))

nFileSizeHigh
High-order DWORD value of the file size, in bytes. This value is zero unless the file size is greater than MAXDWORD. The size of the file is equal to (nFileSizeHigh * (MAXDWORD+1)) + nFileSizeLow.

nFileSizeLow
Low-order DWORD value of the file size, in bytes.


выделение сохранил из MSDN :)
НО. Нельзя копировать бездумно. Сумма двух dword-ов, это тоже dword, и в данном случае - нулик.
Вы зря не обратили внимания на п.1 из [4]
Если это 5-7 гиг, то nFileSizeHigh=1, и умножение на MAXDWORD не приводит к переполнению. Суммарная ошибка - всего 1 байт, который можно не заметить.
Для 9 гиг  будет уже nFileSizeHigh=2, а результат произведения на MAXDWORD - 4294967294.
Почувствуйте разницу.
Ибо результатом произведения двух dword-ов будет dword

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


 
GMax   (2006-12-22 20:33) [11]

вот так делаю я.
это чем-то плохо ?

function GetFileSize64(FN: String): Int64;
var
 FD : TWin32FileAttributeData;
begin
 Result := -1;
 if GetFileAttributesEx(PChar(FN),GetFileExInfoStandard,@FD) then begin
   I64(Result).Hi:=FD.nFileSizeHigh;
   I64(Result).Lo:=FD.nFileSizeLow;
 end;
end;

правда дельфи23 не учитываю, тк не имею


 
MTsv DN ©   (2006-12-22 22:03) [12]

2 Galkov © - снимаю шляпу...
[6] - реально рабочий код... Мой в ауте :( Проверено на файле >10GB



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

Текущий архив: 2007.08.05;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.027 c
4-1172080043
sinir
2007-02-21 20:47
2007.08.05
как распознать 2 мыши на одном компе


2-1183966562
0xFF01
2007-07-09 11:36
2007.08.05
FocusRect


15-1183705117
DelphiN!
2007-07-06 10:58
2007.08.05
Разрешить учетной записи пользователя устанавливать программы


8-1162310301
Jimmy
2006-10-31 18:58
2007.08.05
Кривые Безье


2-1183996257
hgd
2007-07-09 19:50
2007.08.05
Процедура sleep