Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Neuen Beitrag zur Code-Library hinzufügen (https://www.delphipraxis.net/33-neuen-beitrag-zur-code-library-hinzufuegen/)
-   -   Delphi Dateigröße als String ausgeben (https://www.delphipraxis.net/129958-dateigroesse-als-string-ausgeben.html)

robinWie 28. Feb 2009 13:03


Dateigröße als String ausgeben
 
Ich hab eine kleine Routine geschrieben mit der man sich die Dateigröße einer Datei als String ausgeben lasse kann. Die Dateigröße wird als Zahl so klein wie möglich ausgegeben und mit der entsprechenden Einheit versehen. Verwendet werden Binärpräfixe (Kibibyte, Mebibyte... (umrechnungfaktor 1024))

Beispiel
Dateigröße: 12288 Byte
Ausgabe: 1,5 MiB

Bei einem Fehler wird 'ERR' ausgegeben. Wenn die Datei nicht existiert wird 'FNE' ausgegeben.

Parameter:
FileName: dürfte klar sein^^
Digits: Anzahl der Nachkommastellen bei der Ausgabe

Delphi-Quellcode:
function GetFileSizeAsString(FileName: string; Digits: integer = 2): string;
var
F: File;
Size: Extended;
_Unit: integer;
S: string;
begin
if not FileExists(FileName) then
  begin
    Result := 'FNE';
    Exit;
  end;

try
  AssignFile(F, FileName);
  Reset(F);
  _Unit := 0;

  Size := FileSize(F) / 8; // Size in KiB
  CloseFile(F);

  while (Size >= 1024) and (_Unit < 7 ) do
    begin
      Size := Size / 1024;
      Inc(_Unit);
    end;

  case _Unit of
    0: S := 'KiB'; // Size in Kibibyte
    1: S := 'MiB'; // Size in Mebibyte
    2: S := 'GiB'; // Size in Gibibyte
    3: S := 'TiB'; // Size in Tebibyte
    4: S := 'PiB'; // Size in Pebibyte
    5: S := 'EiB'; // Size in Exbibyte
    6: S := 'ZiB'; // Size in Zebibyte
    7: S := 'YiB'; // Size in Yobibyte
  end;

  Result := FloatToStrF(Size, ffFixed, 15, Digits) + ' ' + S;
except
  Result := 'ERR';
end;
end;

DeddyH 28. Feb 2009 13:06

Re: Dateigröße als String ausgeben
 
Da fehlt ein CloseFile, oder habe ich das übersehen?

robinWie 28. Feb 2009 13:16

Re: Dateigröße als String ausgeben
 
ne hase nich übersehen.. hab ich glatt vergessen :oops:

Neutral General 28. Feb 2009 13:21

Re: Dateigröße als String ausgeben
 
Hi,

Also der Code ist noch nicht so ganz ideal... Hab die Funktion mit ner ca. 450KB großen Datei aufgerufen und du kannst dir vorstellen was ich zurück bekommen habe...

"0,00 YiB"

Also ich will keine 450KB Datei in YiB ausgegeben haben :stupid:

Edit: Ich würde sogar fast behaupten, dass deine Funktion bei allen (normalsterblichen) Dateien "0,00 YiB" ausgibt. Denn so groß ist keine Datei -.-

Edit2: War zu faul zum rechnen und habs aus Spaß mal bei einer 4GB Datei probiert (FAT32 kann imo nichtmal größere Dateien verwalten wenn ich mich richtig erinnere) und das Ergebnis ist selbst bei so einer riesigen Datei 0,00 YiB.

DeddyH 28. Feb 2009 13:25

Re: Dateigröße als String ausgeben
 
Zitat:

Delphi-Quellcode:
Size := FileSize(F) / 8;

Sicher, dass das so stimmt? FileSize ist doch in Byte, oder irre ich mich?

robinWie 28. Feb 2009 13:25

Re: Dateigröße als String ausgeben
 
Zitat:

Zitat von Neutral General
Hi,

Also der Code ist noch nicht so ganz ideal... Hab die Funktion mit ner ca. 450KB großen Datei aufgerufen und du kannst dir vorstellen was ich zurück bekommen habe...

"0,00 YiB"

Also ich will keine 450KB Datei in YiB ausgegeben haben :stupid:

Edit: Ich würde sogar fast behaupten, dass deine Funktion bei allen (normalsterblichen) Dateien "0,00 YiB" ausgibt. Denn so groß ist keine Datei -.-

joa hab mich vertan.. statt den or muss da ein and hin. Hab is mir beim blick drauf auch aufgefallen -.-

Zitat:

Zitat von DeddyH
Size := FileSize(F) / 8;
Sicher, dass das so stimmt? FileSize ist doch in Byte, oder irre ich mich?

Ich hatte das erst anders aber dann war das Ergebniss der größe immer eine andere im im windows explorer. Hab dann ein bischen rumexperimentier und rausgefunden wenn ich FileSize durch 8 teile passt das mit den KiB. Ich denke also mal, dass FileSize die größe in Kilobit ausgibt. In der Delphihilfe hab ich nix genaues zu FileSize gefunden, nur dass mir das die Dateigröße ausgibt -.-

Neutral General 28. Feb 2009 13:29

Re: Dateigröße als String ausgeben
 
Hi,

Ok es geht schon besser. Aber bei meiner 4GB Datei spuckt er mir 0,00KiB aus :mrgreen:

robinWie 28. Feb 2009 13:35

Re: Dateigröße als String ausgeben
 
Habs gerade getestet, bei mir funzt es aber...

So hab ichs bei mir aufgebaut:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin
  opendialog1.Execute;
  ShowMessage(GetFileSizeAsString(opendialog1.FileName));
end;

DeddyH 28. Feb 2009 13:47

Re: Dateigröße als String ausgeben
 
Ich hab das Ganze mal ein wenig erweitert:
Delphi-Quellcode:
function GetFileSizeAsString(FileName: string; Use1024: Boolean = true): string;
const Sizes1024: array[0..7] of string = ('KiB','MiB','GiB','TiB','PiB','EiB','ZiB','YiB');
      Sizes1000: array[0..7] of string = ('KB','MB','GB','TB','PB','EB','ZB','YB');
var
  F: File of Byte; //um sicherzugehen
  Size: Extended;
  _Unit: integer;
  S: string;
  Divisor: Integer;
begin
  if not FileExists(FileName) then
    begin
      Result := 'FNE';
      Exit;
    end;

  if Use1024 then
    Divisor := 1024
  else
    Divisor := 1000;

  try
    AssignFile(F, FileName);
    FileMode := fmOpenRead; //damit auch schreibgeschützte Dateien geöffnet werden können
    Reset(F);
    _Unit := Low(Sizes1024);

    Size := FileSize(F) / Divisor; // Size in KiB or KB
    CloseFile(F);

    while (Size >= Divisor) and (_Unit < High(Sizes1024)) do
      begin
        Size := Size / Divisor;
        Inc(_Unit);
      end;

    if Use1024 then
      S := Sizes1024[_Unit]
    else
      S := Sizes1000[_Unit];

    Result := Format('%.2f %s',[Size,S]);
  except
    Result := 'ERR';
  end;
end;

Luckie 28. Feb 2009 13:56

Re: Dateigröße als String ausgeben
 
Warum werden hier die veralteten Pascal Routinen bemüht?

Delphi-Quellcode:
function GetFileSize(Filename: string): Int64;
var
  fFile            : THandle;
  wfd              : TWIN32FINDDATA;
begin
  result := -1;
  if not FileExists(Filename) then
    exit;
  fFile := FindFirstfile(pchar(Filename), wfd);
  if fFile = INVALID_HANDLE_VALUE then
    exit;
  result := (wfd.nFileSizeHigh * (Int64(MAXDWORD) + 1)) + wfd.nFileSizeLow;
  windows.FindClose(fFile);
end;
Oder man nutzt MSDN-Library durchsuchenGetFileSizeEx.

DeddyH 28. Feb 2009 14:03

Re: Dateigröße als String ausgeben
 
Ich denke, mit den veralteten Pascal-Routinen dürfte es auch unter Linux mit Lazarus funktionieren (ungetestet).

robinWie 28. Feb 2009 14:18

Re: Dateigröße als String ausgeben
 
Ich hab die überarbeitete Version von DeddyH mit dem einwand von Lucki kombiniert. Dabei bin ich davon ausgegangen, dass die Methode von Lucki die Größe in Byte liefert. Wenns anders ist bitte schreit ;)

Delphi-Quellcode:
function GetFileSizeAsString(FileName: string; Use1024: Boolean = true): string;
const Sizes1024: array[0..7] of string = ('KiB','MiB','GiB','TiB','PiB','EiB','ZiB','YiB');
      Sizes1000: array[0..7] of string = ('KB','MB','GB','TB','PB','EB','ZB','YB');
var
  Size: Extended;
  _Unit: integer;
  S: string;
  Divisor: Integer;

  fFile: THandle;
  wfd: TWin32FINDDATA;
begin
  if not FileExists(FileName) then
    begin
      Result := 'FNE';
      Exit;
    end;

  try

    fFile := FindFirstfile(PChar(FileName), wfd);
    if fFile = INVALID_HANDLE_VALUE then
      begin
        Result := 'ERR';
        Exit;
      end;
 
    if Use1024 then
      Divisor := 1024
    else
      Divisor := 1000;

    Size := ((wfd.nFileSizeHigh * (Int64(MAXDWORD) + 1)) + wfd.nFileSizeLow) / Divisor; // Size in Kib or KB
    windows.FindClose(fFile);    

    _Unit := Low(Sizes1024);

    while (Size >= Divisor) and (_Unit < High(Sizes1024)) do
      begin
        Size := Size / Divisor;
        Inc(_Unit);
      end;

    if Use1024 then
      S := Sizes1024[_Unit]
    else
      S := Sizes1000[_Unit];

    Result := Format('%.2f %s',[Size,S]);
  except
    Result := 'ERR';
  end;
end;

DeddyH 28. Feb 2009 14:24

Re: Dateigröße als String ausgeben
 
Dann nimm aber die Tippfehler noch raus.
Delphi-Quellcode:
wfd: TWin32FINDDATA;
...
fFile := FindFirstfile(PChar(FileName), wfd);
...
Size := ((wfd.nfileSizeHigh * (int64(MAXDWORD) + 1)) + wfd.nFileSizeLow) / Divisor;

robinWie 28. Feb 2009 14:30

Re: Dateigröße als String ausgeben
 
Ich muss mal n wach macher trinken^^

aber der
Delphi-Quellcode:
Size := ((wfd.nfileSizeHigh * (int64(MAXDWORD) + 1)) + wfd.nFileSizeLow) / Divisor;
is doch richtig. Die Klammen müssen da ja wegen dem "+" hin ;)

DeddyH 28. Feb 2009 14:32

Re: Dateigröße als String ausgeben
 
Du hattest aber
Zitat:

Delphi-Quellcode:
wfd-nFileSizeLow //- statt .

da stehen ;)

robinWie 28. Feb 2009 14:34

Re: Dateigröße als String ausgeben
 
mmh.. ich werd heute mal delphi ausmachen.. das wird eh nix mehr^^

igel457 28. Feb 2009 14:43

Re: Dateigröße als String ausgeben
 
Vielleicht sollte man anstatt der Win32-API-Funktionen auch TFileStream verwenden. Dann läuft das ganze nämlich auch unter Linux und mit Dateigrößen > 2GB (Integer).

DeddyH 28. Feb 2009 15:10

Re: Dateigröße als String ausgeben
 
Gute Idee.
Delphi-Quellcode:
function GetFileSizeAsString(const FileName: string; Use1024: Boolean = true): string;
const Sizes1024: array[0..7] of string = ('KiB','MiB','GiB','TiB','PiB','EiB','ZiB','YiB');
      Sizes1000: array[0..7] of string = ('KB','MB','GB','TB','PB','EB','ZB','YB');
var
  Size: Extended;
  _Unit: integer;
  S: string;
  Divisor: Integer;
  fStream: TFileStream;
begin
  if not FileExists(FileName) then
    begin
      Result := 'FNE';
      Exit;
    end;

  try
    if Use1024 then
      Divisor := 1024
    else
      Divisor := 1000;

    fStream := TFileStream.Create(FileName,fmOpenRead or fmShareDenyNone);
    try
      Size := fStream.Size / Divisor;
    finally
      fStream.Free;
    end;
 
    _Unit := Low(Sizes1024);

    while (Size >= Divisor) and (_Unit < High(Sizes1024)) do
      begin
        Size := Size / Divisor;
        Inc(_Unit);
      end;

    if Use1024 then
      S := Sizes1024[_Unit]
    else
      S := Sizes1000[_Unit];

    Result := Format('%.2f %s',[Size,S]);
  except
    Result := 'ERR';
  end;
end;
[edit] den Filename-Parameter als const definiert. [/edit]

Satty67 28. Feb 2009 15:23

Re: Dateigröße als String ausgeben
 
Welchen Datentyp verwenden neuere Delphi für TFileStream.Size? Mein leicht angegrautes D5 nur LongInt (also 2 GB max).

Rein theoretisch könnte auch ein Singe weit mehr als ein YB darstellen, oder?

DeddyH 28. Feb 2009 15:24

Re: Dateigröße als String ausgeben
 
Unter Delphi 2007 ist das ein Int64.

Satty67 28. Feb 2009 15:28

Re: Dateigröße als String ausgeben
 
Also irgendwo im ExaByte Bereich Schluß? :gruebel:

DeddyH 28. Feb 2009 15:34

Re: Dateigröße als String ausgeben
 
Das hab ich jetzt nicht nachgerechnet :lol:

Hawkeye219 28. Feb 2009 15:35

Re: Dateigröße als String ausgeben
 
Hallo,

ich würde die Ermittlung der Dateigröße von deren Formatierung trennen. Die einzelnen Routinen sind dann universeller einsetzbar.

Gruß Hawkeye

robinWie 28. Feb 2009 15:39

Re: Dateigröße als String ausgeben
 
Zitat:

Zitat von Satty67
Also irgendwo im ExaByte Bereich Schluß? :gruebel:

Könnt sein aber welche Datei ist schon vonner Dateigrößte im ExaByte betreich? :D

Satty67 28. Feb 2009 15:54

Re: Dateigröße als String ausgeben
 
Liste der Anhänge anzeigen (Anzahl: 1)
Also finde so große Zahlen faszinierend und kopiere mir auch fleißig Euren Code ;)
INT64 ist die größte Integer Zahl in D5, da hab ich mir halt gemerkt, das die 9,2 ExaByte fassen kann (wenn es überhaupt richtig ist :lol: )

Zitat:

Zitat von robinWie
Könnt sein aber welche Datei ist schon vonner Dateigrößte im ExaByte betreich? :D

Naja... also Euer Code da oben... ähem... also... ach egal. Mein erster PC hatte Anfang der 90er eine richtig teure 10 MB Festplatte und die hab' ich sogar noch. Wer weis was da noch kommt...

(Hoffe bin nicht zu OT hier)

Cyf 28. Feb 2009 20:57

Re: Dateigröße als String ausgeben
 
NTFS unterstützt derzeit sowieso nur 16TiB als Maximalgröße einer Datei. :wink:

DeddyH 28. Feb 2009 21:22

Re: Dateigröße als String ausgeben
 
Naja, immerhin sind wir so auch für die Zukunft gerüstet :lol:

s.h.a.r.k 13. Feb 2010 11:17

Re: Dateigröße als String ausgeben
 
Zitat:

Zitat von DeddyH
Gute Idee.
Delphi-Quellcode:
function GetFileSizeAsString(const FileName: string; Use1024: Boolean = true): string;
const Sizes1024: array[0..7] of string = ('KiB','MiB','GiB','TiB','PiB','EiB','ZiB','YiB');
      Sizes1000: array[0..7] of string = ('KB','MB','GB','TB','PB','EB','ZB','YB');
var
  Size: Extended;
  _Unit: integer;
  S: string;
  Divisor: Integer;
  fStream: TFileStream;
begin
  if not FileExists(FileName) then
    begin
      Result := 'FNE';
      Exit;
    end;

  try
    if Use1024 then
      Divisor := 1024
    else
      Divisor := 1000;

    fStream := TFileStream.Create(FileName,fmOpenRead or fmShareDenyNone);
    try
      Size := fStream.Size / Divisor;
    finally
      fStream.Free;
    end;
 
    _Unit := Low(Sizes1024);

    while (Size >= Divisor) and (_Unit < High(Sizes1024)) do
      begin
        Size := Size / Divisor;
        Inc(_Unit);
      end;

    if Use1024 then
      S := Sizes1024[_Unit]
    else
      S := Sizes1000[_Unit];

    Result := Format('%.2f %s',[Size,S]);
  except
    Result := 'ERR';
  end;
end;
[edit] den Filename-Parameter als const definiert. [/edit]

Deine Methode ist leider falsch :zwinker: Dein Stream gibt die Bytes und keine KiloBytes zurück. Du fängst bei deiner Zählung aber schon mit KB an. Somit kommt immer eine Einheit größer raus, als es sollte. Habe mir gerade über eine 7,1 TiB große Datei gewundert.

Zudem habe ich die Formatierung von der Ermittlung der Dateigröße getrennt:
Delphi-Quellcode:
{ Diese Methode gibt die Dateigröße in Byte zurück. Dafür wird intern TFileStream verwendet, um auch
  unter Linux lauffähig zu sein. }
function GetFileSize(const AFileName: String): Int64;
var
  fileStream: TFileStream;
begin
  if (not FileExists(AFilename)) then
    raise Exception.Create('File does not exist.');

  // TFileStream nutzen, sodass das Ding auch unter Linux laufen könnte ;)
  fileStream := TFileStream.Create(AFileName,fmOpenRead or fmShareDenyNone);
  try
    Result := fileStream.Size;
  finally
    fileStream.Free();
  end;
end;

{ Diese Methode formatiert die Dateigröße und nutzt dafür das passende Format. Hier kann zudem auch
  noch angegeben werden, ob mit 2^10 oder 1000  gerechnet werden soll, was sich auf die Einheit
  auswirkt. }
function FormatFileSize(const AFileSize: Int64; Use1024: Boolean = True): String;
const
  Sizes1024: array[0..8] of string = ('Bytes', 'KiB','MiB','GiB','TiB','PiB','EiB','ZiB','YiB');
  Sizes1000: array[0..8] of string = ('Bytes', 'KB','MB','GB','TB','PB','EB','ZB','YB');
var
  _size: Extended;
  _Unit: integer;
  s: string;
  Divisor: Integer;
begin
  try
    if (Use1024) then
      Divisor := 1024
    else
      Divisor := 1000;

    _size := AFileSize;
    _Unit := Low(Sizes1024);

    while (_size >= Divisor) and (_Unit < High(Sizes1024)) do
    begin
      _size := _size / Divisor;
      Inc(_Unit);
    end;

    if (Use1024) then
      s := Sizes1024[_Unit]
    else
      s := Sizes1000[_Unit];

    Result := Format('%.2f %s', [_size, s]);
  except
    Result := 'ERR';
  end;
end;

Aphton 14. Feb 2010 18:00

Re: Dateigröße als String ausgeben
 
[OT]
Zitat:

Zitat von wikipedia
The kibibyte is a multiple of the unit byte for quantities of digital information. The binary prefix kibi means 1024, therefore 1 kibibyte is 1024bytes. The unit symbol for the kibibyte is KiB.[1] The unit was established by the International Electrotechnical Commission (IEC) in 2000 and has been accepted for use by all major standards organizations. It was designed to replace the kilobyte used in some computer science contexts to mean 1024 bytes, which conflicts with the SI definition of the prefix kilo.

Obwohl nun seit 2000 feststeht, dass 1024 Bytes = 1 KiB <> 1 KB (wusst ich gar nicht), wird heute ausschließlich die zweitere Darstellung verwendet, soweit ich mich nicht täusche. Warum?
[/OT]

himitsu 14. Feb 2010 18:15

Re: Dateigröße als String ausgeben
 
Zitat:

Zitat von Aphton
Warum?

Sowas wurde hier schon mehrmals diskutiert ... unteranderem wohl auch dort http://www.delphipraxis.net/internal...t.php?t=170328

implementation 14. Feb 2010 18:42

Re: Dateigröße als String ausgeben
 
Zitat:

Zitat von Cyf
NTFS unterstützt derzeit sowieso nur 16TiB als Maximalgröße einer Datei. :wink:

Owned, ext4 ünterstützt Dateien bis zu 1 EiB. :angel:
Unter Linux dürfte es also nützlich sein, dass die Routine mit PiB und EiB arbeiten kann.

xZise 19. Feb 2010 22:05

Re: Dateigröße als String ausgeben
 
Nur so als Idee, könnte man nicht gerade bei der Binärdarstellung trixen, weil das ja immer 2^(10*n) ist? Das man da irgendwie rumshiftet? Also jetzt mal als Spontanidee:
Delphi-Quellcode:
i := <größe>
while (i > 1024) do
  i := i shl 10;
Ungetestet und nur hier mal kurz eingetippt.

MfG
Fabian


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:19 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz