Autor Beitrag
n-regen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 202
Erhaltene Danke: 2



BeitragVerfasst: Mi 10.09.08 11:52 
Hallo!

Ich habe eine Funktion (keine Unit!) geschrieben, die aus einem Int64 mit einer Dateigröße einen String macht und dabei den Wert soweit herunterrechnet, dass er in der größten Einheit ausgegebn wird, in der er nicht als 0,xy-Zahl erscheint.
Also beispielsweise:
  • 0 -> 0 Bytes
  • 1023 -> 1023 Bytes
  • 1024 -> 1,00 KiloByte
  • 1048576 -> 1,00 MegaByte
  • usw.
Die Funktion rechnet bis TeraBytes. Also käme bei FileSize=1125899906842624, als Ergebnis "1024 TeraBytes" raus.
Man kann außerdem über den Boolean-Wert "LongText" bestimmen, ob im String z.B. "MegaBytes" oder "MB" stehen soll.

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
function FileSizeToStr(FileSize: Int64; LongText:Boolean=False):String;
begin
 if FileSize < 1024 //Bytes (0-1023)
 then begin
  if LongText
  then Result := IntToStr(FileSize)+' Bytes'
  else Result := IntToStr(FileSize)+' B';
 end;
 if (FileSize >= 1024and (FileSize < 1048576//KiloBytes (1024-1048575)
 then begin
  if LongText
  then Result := FloatToStrF(FileSize / 1024, ffNumber, 152)+' KiloBytes'
  else Result := FloatToStrF(FileSize / 1024, ffNumber, 152)+' KB';
 end;
 if (FileSize >= 1048576and (FileSize < 1073741824//MegaBytes (1048576-1073741823)
 then begin
  if LongText
  then Result := FloatToStrF(FileSize / 1048576, ffNumber, 152)+' MegaBytes'
  else Result := FloatToStrF(FileSize / 1048576, ffNumber, 152)+' MB';
 end;
 if (FileSize >= 1073741824and (FileSize < 1099511627776//GigaBytes (1073741824-1099511627775)
 then begin
  if LongText
  then Result := FloatToStrF(FileSize / 1073741824, ffNumber, 152)+' GigaBytes'
  else Result := FloatToStrF(FileSize / 1073741824, ffNumber, 152)+' GB';
 end;
 if (FileSize >= 1099511627776//TeraBytes (ab 1099511627776)
 then begin
  if LongText
  then Result := FloatToStrF(FileSize / 1099511627776, ffNumber, 152)+' TeraBytes'
  else Result := FloatToStrF(FileSize / 1099511627776, ffNumber, 152)+' TB';
 end;
 if (Result[1] = '1'and (Result[2] = ','and LongText
 then Result := Copy(Result, 0, Length(Result)-1);
end;


Ich hoffe, dass irgendjemand diese Funktion brauchen kann und bin natürlich für Verbesserungswünsche offen.

Nils


Zuletzt bearbeitet von n-regen am Mi 10.09.08 13:53, insgesamt 1-mal bearbeitet
Hidden
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2242
Erhaltene Danke: 55

Win10
VS Code, Delphi 2010 Prof.
BeitragVerfasst: Mi 10.09.08 12:43 
Hi,

Ich habe deinen Quelltext mal nachformatiert und ein wenig übersichtlicher gemacht. Kann noch optimiert werden, ich wollte möglichst wenig ändern, daher die unnötigen Zwischenvariablen.

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
function FileSizeToStr(FileSize: Int64; LongText:Boolean=False): String;
const
  LongNames: Array[0..4of String = ('Bytes''KiloBytes''MegaBytes',
                                    'GigaBytes''TeraBytes');
  ShortNames: Array[0..4of String = ('B''KB''MB''GB''TB');
var
  RestSize: Int64;
  MultiFactor: Int64;  //Faktor, den die Einheit darstellt(KB = 1024..)
  DataUnit: Integer;  //B, KB, .. durchnummeriert
  DataUnitName: String;
begin
  DataUnit := 0;  //Starteinheit Bytes
  RestSize := FileSize;
  While FileSize >= 1024 do begin
    RestSize := RestSize div 1024;  //nächste Einheit
    MultiFactor := MultiFactor * 1024;  //könnte auch direkt jedes Mal teilen, wollte aber keine zerstückelten Kommazahlen
    Inc(DataUnit);
  end;
  if LongText then
    DataUnitName := LongNames[DataUnit]
  else DataUnitName := ShortNames[DataUnit];
  Result := FloatToStrF(FileSize / MultiFactor, ffNumber, 152) +
              ' ' + DataUnitName;
  (*if FileSize < 1024 then begin  //Bytes (0-1023)
    if LongText then
      Result := IntToStr(FileSize) + ' Bytes'
    else Result := IntToStr(FileSize) + ' B';
  end;
  if (FileSize >= 1024) and (FileSize < 1048576) then begin  //KiloBytes (1024-1048575)
    if LongText then
      Result := FloatToStrF(FileSize / 1024, ffNumber, 15, 2) + ' KiloBytes'
    else Result := FloatToStrF(FileSize / 1024, ffNumber, 15, 2) + ' KB';
  end;
  if (FileSize >= 1048576) and (FileSize < 1073741824) then begin  //MegaBytes (1048576-1073741823)
    if LongText then
      Result := FloatToStrF(FileSize / 1048576, ffNumber, 15, 2) + ' MegaBytes'
    else Result := FloatToStrF(FileSize / 1048576, ffNumber, 15, 2) + ' MB';
  end;
  if (FileSize >= 1073741824) and (FileSize < 1099511627776) then begin  //GigaBytes (1073741824-1099511627775)
    if LongText then
      Result := FloatToStrF(FileSize / 1073741824, ffNumber, 15, 2) + ' GigaBytes'
    else Result := FloatToStrF(FileSize / 1073741824, ffNumber, 15, 2) + ' GB';
  end;
  if (FileSize >= 1099511627776) then begin  //TeraBytes (ab 1099511627776)
    if LongText then
      Result := FloatToStrF(FileSize / 1099511627776, ffNumber, 15, 2) + ' TeraBytes'
    else Result := FloatToStrF(FileSize / 1099511627776, ffNumber, 15, 2) + ' TB';
  end;  *)

  if (Result[1] = '1'and (Result[2] = ','then
    Result := Copy(Result, 0, Length(Result) - 1);
end;


Edit: Aso, fehlt noch eine Austrittsbedingung aus der Schleife, wenn Terabyte erreicht sind.
E2: Kommentare drangemacht :)

mfG,

_________________
Centaur spears can block many spells, but no one tries to block if they see that the spell is a certain shade of green. For this purpose it is useful to know some green stunning hexes. (HPMoR)
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10181
Erhaltene Danke: 1254

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Mi 10.09.08 12:48 
Moin!

Hier mein Vorschlag: ;)
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
function PrettyFileSize(const AFileSize: Int64; ADecimals: Integer = 0const ALongUnit: Boolean = FALSE): String;
  const
    Units: array[0..5,Boolean] of String = (
      ('B','Byte'),
      ('KB','KiloByte'),
      ('MB','MegaByte'),
      ('GB','GigaByte'),
      ('TB','TeraByte'),
      ('PB','PetaByte')
    );
  var
    TempSize, UnitValue: Int64;
    UnitIndex: Integer;
begin
  TempSize := AFileSize;
  UnitValue := 1;
  UnitIndex := 0;
  while ((TempSize shr 10) > 0and (UnitIndex < High(Units)) do begin
    TempSize := TempSize shr 10;
    UnitValue := UnitValue shl 10;
    Inc(UnitIndex);
  end;
  if (UnitIndex = 0then
    ADecimals := 0;
  Result := Format('%.*f %s',[ADecimals,AFileSize/UnitValue,Units[UnitIndex,ALongUnit]]);
end;
cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
Hidden
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2242
Erhaltene Danke: 55

Win10
VS Code, Delphi 2010 Prof.
BeitragVerfasst: Mi 10.09.08 12:50 
user profile iconNarses hat folgendes geschrieben:
Units: array[0..5, Boolean] of String

Wusste garnicht, dass das möglich ist :shock:

_________________
Centaur spears can block many spells, but no one tries to block if they see that the spell is a certain shade of green. For this purpose it is useful to know some green stunning hexes. (HPMoR)
n-regen Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 202
Erhaltene Danke: 2



BeitragVerfasst: Mi 10.09.08 13:24 
So viel, wie man an dieser Funktion verändern und verbessern kann, könnte man die glatt als Beispiel in einem Lehrbuch hernehmen!
Freut mich jedenfalls, dass sich jemand dafür interessiert. ;-)

Nils
Hidden
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2242
Erhaltene Danke: 55

Win10
VS Code, Delphi 2010 Prof.
BeitragVerfasst: Mi 10.09.08 13:36 
user profile iconn-regen hat folgendes geschrieben:
So viel, wie man an dieser Funktion verändern und verbessern kann, könnte man die glatt als Beispiel in einem Lehrbuch hernehmen!
Freut mich jedenfalls, dass sich jemand dafür interessiert. ;-)

Nils

Jemand Lust, das in Asm-Code zu übersetzen und, die Veröffentlichung zu übernehmen? :lol:

_________________
Centaur spears can block many spells, but no one tries to block if they see that the spell is a certain shade of green. For this purpose it is useful to know some green stunning hexes. (HPMoR)
n-regen Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 202
Erhaltene Danke: 2



BeitragVerfasst: Mi 10.09.08 13:50 
user profile iconHidden hat folgendes geschrieben:
Jemand Lust, das in Asm-Code zu übersetzen und, die Veröffentlichung zu übernehmen? :lol:

Wieso Assembler (das meinst du doch mit Asm, oder?)?
Und in den meisten Delphi-Büchern kommt irgendwo was vor: "Was könnte man an dieser Prozedur/Funktion noch besser machen?"
Und für sowas wäre diese Funktion eben gut.

EDIT: Mir ist noch ein Fehler aufgefallen:
Statt
ausblenden Delphi-Quelltext
1:
2:
 if (Result[1] = '1'and (Result[2] = ',')
 then Result := Copy(Result, 0, Length(Result)-1);

muss es
ausblenden Delphi-Quelltext
1:
2:
 if (Result[1] = '1'and (Result[2] = ','and LongText
 then Result := Copy(Result, 0, Length(Result)-1);

heißen.
Sonst entfernt er nicht nur das s von Bytes, wenn der Ausgabe-String mit 1, anfängt, sondern unter Umständen auch das B von MB o.ä.
Hidden
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 2242
Erhaltene Danke: 55

Win10
VS Code, Delphi 2010 Prof.
BeitragVerfasst: Mi 10.09.08 14:36 
Müsste der Startindex bei Copy nicht 1 sein?

Edit: Würde Gausi's Version nicht bei anderen Boolean-Werten als true und false 'ne Exception werfen?

mfG,

_________________
Centaur spears can block many spells, but no one tries to block if they see that the spell is a certain shade of green. For this purpose it is useful to know some green stunning hexes. (HPMoR)
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: Mi 10.09.08 15:13 
Hier ist auch noch ein semantischer Fehler drin ;-)

1 000 000 Bytes = 1 MB
1 048 576 Bytes = 1 MiB

Das gilt genauso für die Langfassungen ;-)

vgl. xkcd.com/394/

Ach ja: EiB fehlt auch noch bei den Einheiten ;-)

_________________
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10181
Erhaltene Danke: 1254

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Mi 10.09.08 18:08 
Moin!

user profile iconHidden hat folgendes geschrieben:
Müsste der Startindex bei Copy nicht 1 sein?
Würde ich auch sagen. ;)

user profile iconHidden hat folgendes geschrieben:
Edit: Würde Gausi's Version nicht bei anderen Boolean-Werten als true und false 'ne Exception werfen?
a) Was hat user profile iconGausi damit zu tun? :gruebel:
b) Welche Werte für den Delphi-Datentyp Boolean kennst du noch, ausser [True, False]? :shock:

user profile iconBenBE hat folgendes geschrieben:
Hier ist auch noch ein semantischer Fehler drin ;-)
Nun, das liegt im Auge des Betrachters, der bevorzugten Norm oder der historischen Herleitung... :) In meinen Augen ist KB einfach logischer, also KiBiByte&Co und abgesehen davon gefällt es mir besser... :mrgreen:

user profile iconBenBE hat folgendes geschrieben:
Ach ja: EiB fehlt auch noch bei den Einheiten ;-)
Ist ja zum Glück Open-Source... :P

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
n-regen Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 202
Erhaltene Danke: 2



BeitragVerfasst: Mi 10.09.08 18:14 
user profile iconBenBE hat folgendes geschrieben:
Hier ist auch noch ein semantischer Fehler drin ;-)
[...]
Ach ja: EiB fehlt auch noch bei den Einheiten ;-)


1. finde ich die griechischen Einheiten wesentlich klangvoller als die ver-i-ten, neuen Einheiten.
2. habe ich im Eingangspost darauf hingewiesen, dass bei Terybyte - nein nicht Tibibyte ( :puke: ) - Schluss ist.
Und wer hat schon eine Datei/einen Ordner, der mehrere Exabyte groß ist.
Nebenbei bemerkt kommen nach Terabyte erstmal Petabyte (siehe u.a. Wikipedia).