Programowanie w języku Delphi » FAQ

13 komentarzy

Legalnl 2011-08-28 20:26

Najlepiej to chyba tak:

function GetFileSize(const FileName: string):Int64;
 var
    ms : tmemorystream;
 begin
    if not FileExists(FileName) then
       Result:=0
    else
    begin
      ms := tmemorystream.Create;
      ms.LoadFromFile(filename);
      result:=ms.Size;
      Freeandnil(ms);
    end;
 end;

Ładując to do Tfilestream plik nie może być używany, co uniemożliwia chodzby sprawdzenie rozmiaru własnego progrmau. Tmemorystream wczyta wszystko.

ziom213 2008-11-04 23:35

można i tak

function rozmiarpliku(Path:TFileName):int64;
type  Int64Record = record
      case boolean of
        TRUE: (Int:Int64);
        FALSE: (Lo, Hi:DWORD);
        end;
var Search:TSearchRec;
    Handle:THandle;
    Size:Int64Record;
begin
result:=0;
Handle:=CreateFile(PChar(Path), 0, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0);
if (Handle<>INVALID_HANDLE_VALUE) then
          begin
          Size.Lo:=GetFileSize(Handle, @Size.Hi);
          result:=Size.int;
          CloseHandle(Handle);
          end;
end;

homesoftware 2007-07-29 13:35

Uwaga Terrmita jest w pełni uzasadniona. Ma to szczególne znaczenie, gdy chcemy w jakiś konkretny sposób wykorzystać wynik badania konkretnego pliku. Jeśli jednak chcemy jedynie dowiedzieć sie jaka jest suma wielkości zestawu plików, to czy zwrócona wartość będzie zerowa ponieważ plik nie istnieje lub będzie zerowy jego rozmiar, to dla sumy i tak nie ma to znaczenia. Aby jednak funkcja dawała jednoznaczne wyniki to należy zastosować poprawkę Terrmita. Niestety ta funkcja nie uwzględnia katalogów i plików ukrytych i systemowych czyli tych z różnymi ograniczeniami dostępu. Wynik badania np. katalogu WINDOWS daje złe wyniki. Najlepsze rozwiązanie dał Szczawik na forum ('rozmiar plików i katalogów'). Pierwszy algorytm działa wyśmienicie i nadaje się do większości zastosowań: oto on (reszta info na forum):
function GetDirSize(Path:TFileName):int64;
type  Int64Record = record
      case boolean of
        TRUE: (Int:Int64);
        FALSE: (Lo, Hi:DWORD);
        end;
var Search:TSearchRec;
    Handle:THandle;
    Size:Int64Record;
begin
Path:=IncludeTrailingPathDelimiter(Path);
result:=0;
if (FindFirst(Path+'*', faAnyFile, Search) = 0) then
  begin
    repeat
    if (Search.Name<>'.') and (Search.Name<>'..') then
      begin
      if (Search.Attr and faDirectory>0) then
        result:=result+GetDirSize(Path+Search.Name)
      else
        begin
        Handle:=CreateFile(PChar(Path+Search.Name), 0, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0);
        if (Handle<>INVALID_HANDLE_VALUE) then
          begin
          Size.Lo:=GetFileSize(Handle, @Size.Hi);
          result:=result+Size.Int;
          CloseHandle(Handle);
          end;
        end;
      end;
    until (FindNext(Search)<>0);
  FindClose(Search);
  end;
end;


W pomyśle Krzemina jest mały błąd. należy zamienić:
FS.Create(FileName,fmOpenRead or fmShareCompat);
na:
FS:= TFileStream.Create(FileName,fmOpenRead or fmShareCompat);
Reszta działa dobrze i nadaje sie do niektórych zastosowań.

Terrmit 2007-07-25 00:58

Ja bym jeszcze w przykładzie Krzemina zmienił
   if not FileExists(FileName) then
      Result:=0
na
   if not FileExists(FileName) then
      Result:=-1
Wynik -1 wskazywałby wówczas na wystąpienie błędu. Bo przecież mogą być pliki o zormiarze 0. W ten sposób można dodatkowo odróżnić pliki istniejące, ale puste, od nieistniejących.

Coldpeer 2006-02-25 19:07

UnAdamBoduch: a ty pisać poprawnie :)

UnAdamBoduch 2005-09-21 10:06

Marooned naucz się prograować lepeij :D

wotek 2004-04-07 14:42

Owszem, tamat jest prosty, ale nie wszyscy sami potrafia napisac taka funkcje... i to glownie dla nich.

A tak przy okazji - nie zerznalem tego z pliku xyz, ani netu :-p

wotek 2004-04-05 10:05

Dobrze wiedziec jak takie cosik samemu zaimplementowac...

Krzemin 2004-04-01 21:16

Heh, wszystkie sposiby na pobranie rozmiaru pliku (FileSize, FindFirst itp...) mogą nieźle świrować przy wiekszych plikach.
Sam miałem tego typu problem i rozwiązałem go używając klasy TFileStream:

function GetFileSize(const FileName: string):Int64;
var
   FS:TFileStream;
begin
   if not FileExists(FileName) then
      Result:=0
   else
   begin
      FS.Create(FileName,fmOpenRead or fmShareCompat);
      Result:=FS.Size;
      FS.Free;
   end;
end;


Oczywiście powodem wykrzaczania pozostałych sposobów jest zakres, w jakim podają rozmiar pliku (Integer), co w przypadku TFileStream.Size
jest Int64...

flabra 2004-04-02 08:51

Sposobem na ominiecie 'świrowania' przy zwracianiu rozmiaru pliku jest konwersja na typ nieoznaczony....

DWORD(...)     (c/delphi)
(DWORD)...     (tylko c)

... i problem znika. Zresztą tak sie powinno postepować z każdą funkcją/zmienną, która jest, a nie powinna być oznaczona.

ŁF 2004-03-31 19:50

jes też funkcja FileSize... wotek, nie mogłeś znaleźć trudniejszego tematu?

Marooned 2004-03-31 18:18

A nie lepiej FileOpen, Seek, FileClose?

weer01 2004-03-31 17:22

Heh, pewnie to wziąłeś z przykładu do delphi (znajduje się w <delphi>Demos\Doc\Filmanex z pliku FmxUtils.pas... przynajmniej identycznie tam jest rozwiązane:D