Delphi-Funktion zur Anzeige Anzahl der Bytes als Windows-Does
-
18-09-2019 - |
Frage
Dies ist ein einfaches (glaube ich).
Gibt es ein System in Funktion eingebaut, oder eine Funktion, dass jemand erstellt, die von Delphi aufgerufen werden kann, die eine Anzahl von Bytes (zB eine Dateigröße) angezeigt werden, die Art und Weise Windows zeigt in einem Feld Eigenschaften der Datei?
z. Dies ist, wie Windows-Eigenschaftenfeld zeigt verschiedene Größen:
539 bytes (539 bytes)
35.1 KB (35,974 bytes)
317 MB (332,531,365 bytes)
2.07 GB (2,224,617,077 bytes)
Das Display ist intelligent über die Verwendung von Bytes, KB, MB oder GB, und zeigt nur drei signifikante Stellen für das KB, MB und GB. Daraus folgt, dass durch die genaue Anzahl von Bytes in Klammern der Anzeige mit Kommas, um die Tausende zu trennen. Es ist ein sehr schönes Display, gut durchdacht.
Kennt jemand eine solche Funktion?
Edit: Ich bin sehr überrascht, dass es keine Funktion dafür war
.Vielen Dank für Ihre hilfreichen Ideen. Ich habe mit dieser kommen, das scheint zu funktionieren:
function BytesToDisplay(A:int64): string;
var
A1, A2, A3: double;
begin
A1 := A / 1024;
A2 := A1 / 1024;
A3 := A2 / 1024;
if A1 < 1 then Result := floattostrf(A, ffNumber, 15, 0) + ' bytes'
else if A1 < 10 then Result := floattostrf(A1, ffNumber, 15, 2) + ' KB'
else if A1 < 100 then Result := floattostrf(A1, ffNumber, 15, 1) + ' KB'
else if A2 < 1 then Result := floattostrf(A1, ffNumber, 15, 0) + ' KB'
else if A2 < 10 then Result := floattostrf(A2, ffNumber, 15, 2) + ' MB'
else if A2 < 100 then Result := floattostrf(A2, ffNumber, 15, 1) + ' MB'
else if A3 < 1 then Result := floattostrf(A2, ffNumber, 15, 0) + ' MB'
else if A3 < 10 then Result := floattostrf(A3, ffNumber, 15, 2) + ' GB'
else if A3 < 100 then Result := floattostrf(A3, ffNumber, 15, 1) + ' GB'
else Result := floattostrf(A3, ffNumber, 15, 0) + ' GB';
Result := Result + ' (' + floattostrf(A, ffNumber, 15, 0) + ' bytes)';
end;
Dies ist wahrscheinlich gut genug, aber ist es etwas Schöneres?
Lösung
Auch die folgenden Funktionen, die alle im shlwapi Bibliothek .
-
StrFormatByteSizeA
(DWORD-Parameter) -
StrFormatByteSizeW
(Int64-Parameter) -
StrFormatByteSize64
(Im Unicode-Modus, es ist wirklichStrFormatByteSizeW
) -
StrFormatByteSizeEx
(Vista SP2, können Rundungssteuerung)
Jeder von ihnen wird Ihnen den ersten Teil Ihrer gewünschten Anzeigeformat. Überprüfen Sie die Dokumentation oder schreiben Sie Ihre eigenen Tests zu bestätigen, dass sie die Konvertierungen geben Sie erwarten darüber, ob ein Megabyte von 1000 oder 1024 Kilobyte besteht. Für den zweiten Teil des Anzeigeformats, können Sie mit den Antworten auf einen anderen Stack-Überlauf Frage beginnen:
- Wie int Währung konvertieren? (Er war wirklich fragen, wie Kommata, nicht speziell über Geld einwerfen.)
Aber vielleicht diese Frage ist der falsche Weg gibt, da alle Vorschläge zu gehen, sowie FloatToStrF
, scheitert an den oberen Grenzen der Int64
. Sie werden ein paar Bytes verlieren, aber ich halte diese ziemlich wichtig Bytes da der Zweck des zweiten Wertes in diesem Anzeigeformat ist eine genaue Zahl zu liefern.
Wenn Sie alle Stücke haben, kleben sie zusammen. Ich verwende eine hypothetische IntToStrCommas
Funktion hier, und wenn Sie möchten, implementieren, dass als FloatToStrF
, nur zu.
function BytesToDisplay(const num: Int64): string;
var
// If GB is the largest unit available, then 20 characters is
// enough for "17,179,869,183.99 GB", which is MaxUInt64.
buf: array[0..20] of Char;
begin
if StrFormatByteSize64(num, buf, Length(buf)) = nil then
raise EConvertError.CreateFmt('Error converting %d', [num]);
Result := Format('%s (%s bytes)', [buf, IntToStrCommas(num)]);
end;
Andere Tipps
Nicht genau das, was du bist nach, aber ich habe eine Funktion in meiner Bibliothek, die Ihnen eine Idee geben kann, wie dies in Angriff zu nehmen ein:
function FormatByteSize(const bytes: Longword): string;
var
B: byte;
KB: word;
MB: Longword;
GB: Longword;
TB: UInt64;
begin
B := 1; //byte
KB := 1024 * B; //kilobyte
MB := 1000 * KB; //megabyte
GB := 1000 * MB; //gigabyte
TB := 1000 * GB; //teraabyte
if bytes > TB then
result := FormatFloat('#.## TB', bytes / TB)
else
if bytes > GB then
result := FormatFloat('#.## GB', bytes / GB)
else
if bytes > MB then
result := FormatFloat('#.## MB', bytes / MB)
else
if bytes > KB then
result := FormatFloat('#.## KB', bytes / KB)
else
result := FormatFloat('#.## bytes', bytes) ;
end;
Dies ist aus meiner dzlib Einheit u_dzConvertUtils
/// these contants refer to the "Xx binary byte" units as defined by the
/// International Electronical Commission (IEC) and endorsed by the
/// IEE and CiPM </summary>
const
OneKibiByte = Int64(1024);
OneMebiByte = Int64(1024) * OneKibiByte;
OneGibiByte = Int64(1024) * OneMebiByte;
OneTebiByte = Int64(1024) * OneGibiByte;
OnePebiByte = Int64(1024) * OneTebiByte;
OneExbiByte = Int64(1024) * OnePebiByte;
/// <summary>
/// Converts a file size to a human readable string, e.g. 536870912000 = 5.00 GiB (gibibyte) </summary>
function FileSizeToHumanReadableString(_FileSize: Int64): string;
begin
if _FileSize > 5 * OneExbiByte then
Result := Format(_('%.2f EiB'), [_FileSize / OneExbiByte])
else if _FileSize > 5 * OnePebiByte then
Result := Format(_('%.2f PiB'), [_FileSize / OnePebiByte])
else if _FileSize > 5 * OneTebiByte then
Result := Format(_('%.2f TiB'), [_FileSize / OneTebiByte])
else if _FileSize > 5 * OneGibiByte then
Result := Format(_('%.2f GiB'), [_FileSize / OneGibiByte])
else if _FileSize > 5 * OneMebiByte then
Result := Format(_('%.2f MiB'), [_FileSize / OneMebiByte])
else if _FileSize > 5 * OneKibiByte then
Result := Format(_('%.2f KiB'), [_FileSize / OneKibiByte])
else
Result := Format(_('%d Bytes'), [_FileSize]);
end;