Entwickler-Ecke
Open Source Units - "FileSizeToStr" - Dateigrößen in einen String umwandeln
n-regen - Mi 10.09.08 11:52
Titel: "FileSizeToStr" - Dateigrößen in einen String umwandeln
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.
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 then begin if LongText then Result := IntToStr(FileSize)+' Bytes' else Result := IntToStr(FileSize)+' B'; end; if (FileSize >= 1024) and (FileSize < 1048576) then begin 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 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 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 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] = ',') 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
Hidden - 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.
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..4] of String = ('Bytes', 'KiloBytes', 'MegaBytes', 'GigaBytes', 'TeraBytes'); ShortNames: Array[0..4] of String = ('B', 'KB', 'MB', 'GB', 'TB'); var RestSize: Int64; MultiFactor: Int64; DataUnit: Integer; DataUnitName: String; begin DataUnit := 0; RestSize := FileSize; While FileSize >= 1024 do begin RestSize := RestSize div 1024; MultiFactor := MultiFactor * 1024; Inc(DataUnit); end; if LongText then DataUnitName := LongNames[DataUnit] else DataUnitName := ShortNames[DataUnit]; Result := FloatToStrF(FileSize / MultiFactor, ffNumber, 15, 2) + ' ' + DataUnitName; 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,
Narses - Mi 10.09.08 12:48
Moin!
Hier mein Vorschlag: ;)
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 = 0; const 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) > 0) and (UnitIndex < High(Units)) do begin TempSize := TempSize shr 10; UnitValue := UnitValue shl 10; Inc(UnitIndex); end; if (UnitIndex = 0) then ADecimals := 0; Result := Format('%.*f %s',[ADecimals,AFileSize/UnitValue,Units[UnitIndex,ALongUnit]]); end; |
cu
Narses
Hidden - Mi 10.09.08 12:50
Narses hat folgendes geschrieben: |
Units: array[0..5, Boolean] of String |
Wusste garnicht, dass das möglich ist :shock:
n-regen - 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 - Mi 10.09.08 13:36
n-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:
n-regen - Mi 10.09.08 13:50
Hidden 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
Delphi-Quelltext
1: 2:
| if (Result[1] = '1') and (Result[2] = ',') then Result := Copy(Result, 0, Length(Result)-1); |
muss es
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 - 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,
BenBE - 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.
http://xkcd.com/394/
Ach ja: EiB fehlt auch noch bei den Einheiten ;-)
Narses - Mi 10.09.08 18:08
Moin!
Hidden hat folgendes geschrieben: |
Müsste der Startindex bei Copy nicht 1 sein? |
Würde ich auch sagen. ;)
Hidden hat folgendes geschrieben: |
Edit: Würde Gausi's Version nicht bei anderen Boolean-Werten als true und false 'ne Exception werfen? |
a) Was hat
Gausi damit zu tun? :gruebel:
b) Welche Werte für den Delphi-Datentyp
Boolean kennst du noch, ausser
[True, False]? :shock:
BenBE 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:
BenBE hat folgendes geschrieben: |
Ach ja: EiB fehlt auch noch bei den Einheiten ;-) |
Ist ja zum Glück Open-Source... :P
cu
Narses
n-regen - Mi 10.09.08 18:14
BenBE 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 [
http://de.wikipedia.org/wiki/Vors%C3%A4tze_f%C3%BCr_Ma%C3%9Feinheiten]).
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2024 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!