2009-08-17 9 views
6

Dies ist eine einfache (glaube ich).Delphi-Funktion zur Anzeige der Anzahl der Bytes als Windows

Gibt es ein in Funktion eingebautes System oder eine von Delphi erstellte Funktion, die eine Anzahl von Bytes (z. B. eine Dateigröße) anzeigt, wie Windows im Feld Eigenschaften einer Datei angezeigt wird?

z.B. Dies ist, wie Windows Eigenschaftenbox verschiedene Größen zeigt:

539 bytes (539 bytes) 
35.1 KB (35,974 bytes) 
317 MB (332,531,365 bytes) 
2.07 GB (2,224,617,077 bytes) 

Die Anzeige über die Verwendung von Bytes ist smart, KB, MB oder GB, und zeigt nur drei signifikante Stellen für das KB, MB und GB. Dann folgt die Anzeige der genauen Anzahl der Bytes in Klammern mit Kommas, die die Tausender trennen. Es ist ein sehr schönes Display, gut durchdacht.

Kennt jemand eine solche Funktion?


Edit: Ich bin sehr überrascht, dass es für diese keine Funktion war.

Vielen Dank für Ihre hilfreichen Ideen. Ich habe mir das ausgedacht, was zu funktionieren scheint:

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; 

Das ist wahrscheinlich gut genug, aber gibt es etwas besseres?

Antwort

12

Siehe folgende Funktionen, die alle in den shlwapi library.

Irgendwelche von ihnen geben Ihnen den ersten Teil Ihres gewünschten Anzeigeformats. Überprüfen Sie die Dokumentation, oder schreiben Sie Ihre eigenen Tests, um zu bestätigen, dass sie die erwarteten Konvertierungen hinsichtlich der Größe eines Megabyte aus 1000 oder 1024 Kilobyte ergeben. Für den zweiten Teil des Anzeigeformats, können Sie mit den Antworten auf einen anderen Stack-Überlauf Frage beginnen: (. Er war wirklich fragen, wie Komma einfügen, nicht speziell über Geld)

Aber vielleicht ist diese Frage der falsche Weg, da alle Vorschläge dort, sowie FloatToStrF, an den oberen Grenzen von Int64 scheitern. Sie werden einige Bytes verlieren, aber ich betrachte diese ziemlich wichtigen Bytes, da der Zweck des zweiten Werts in diesem Anzeigeformat darin besteht, eine genaue Zahl anzugeben.

Sobald Sie alle Teile haben, kleben Sie sie zusammen. Ich verwende hier eine hypothetische IntToStrCommas Funktion, und wenn Sie das als FloatToStrF implementieren möchten, gehen Sie voran.

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; 
+1

StrFormatByteSize64 scheint zu sein, was Windows für den ersten Teil verwendet. Aber wenn man diese Funktion von Delphi aufruft, muss man einen Puffer einrichten - nicht hübsch. Für den zweiten Teil scheint floattostrf besser zu funktionieren als die Lösungen in Ihrem Link. – lkessler

+0

Da Sie eine Vorstellung davon haben, wie lang die Ausgabe sein kann, verwenden Sie ein gepacktes Array [1..n] von char für den Puffer. Übergeben Sie @CharArray [1] als Zeiger. –

+0

Ausgezeichneter Tipp! (StrFormatByteSizeW) –

5

nicht genau, was Sie wollen, 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; 
+3

Sollte nicht die anderen 1000 auch 1024 das sein? Aber ziemlich knapp. – lkessler

+0

Ja, technisch sollte es 1024x1024x sein ... aber das wurde vor einiger Zeit für einen bestimmten Videoserver geschrieben. Posted als ein einfaches Beispiel – Gerard

+0

Wenn Sie durch 1024 teilen, sollten Sie auch die ISO-Standardeinheiten TiB, GiB, MiB und KiB verwenden. – dummzeuch

0

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; 
Verwandte Themen