2009-08-17 10 views
6

To jest proste (myślę).Funkcja Delphi do wyświetlania liczby bajtów jako Windows Czy

Czy istnieje funkcja wbudowana w system lub funkcja utworzona przez kogoś, którą można wywołać z Delphi, która wyświetli liczbę bajtów (np. Rozmiar pliku), sposób wyświetlania w oknie właściwości pliku?

np. To jest jak pudełko nieruchomość Windows wyświetla różne rozmiary:

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

Wyświetlacz jest mądry na temat korzystania bajtów, KB, MB lub GB, i pokazuje tylko 3 cyfr znaczących dla KB, MB i GB. Wynika z tego, że wyświetlając dokładną liczbę bajtów w nawiasach, przecinkiem są tysiące. To bardzo fajny wyświetlacz, dobrze przemyślany.

Czy ktoś wie o takiej funkcji?


Edytuj: Jestem bardzo zaskoczony, że nie było w tym żadnej funkcji.

Dzięki za pomocne pomysły. Wymyśliłem to, co wydaje się działać:

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; 

To chyba wystarczająco dobrze, ale czy jest coś lepszego?

Odpowiedz

12

zobacz następujące funkcje, a wszystko to w shlwapi library.

Każdy z nich da ci pierwszą porcję pożądanego formatu wyświetlania. Sprawdź dokumentację lub napisz własne testy, aby potwierdzić, że dają oczekiwane konwersje dotyczące tego, czy megabajt składa się z 1000, czy 1024 kilobajtów. Na drugiej części formatu wyświetlania, można zacząć od odpowiedzi na innym przepełnienie stosu pytanie: (. Był naprawdę pytaniem, jak wstawić przecinki, a nie konkretnie o pieniądze)

Ale może to pytanie jest niewłaściwe, ponieważ wszystkie sugestie, a także FloatToStrF, zawodzą w górnej granicy Int64. Stracisz kilka bajtów, ale uważam te dość ważne bajty, ponieważ celem drugiej wartości w tym formacie wyświetlania jest podanie dokładnej liczby.

Po wykonaniu wszystkich części sklej je ze sobą. Używam tutaj hipotetycznej funkcji IntToStrCommas, a jeśli chcesz ją wdrożyć jako FloatToStrF, śmiało.

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 wydaje się być tym, czego Windows używa w pierwszej części. Ale wywołanie tej funkcji z Delphi wymaga ustawienia bufora - nie ładnego. Dla drugiej części, floattostrf wydaje się działać lepiej niż rozwiązania w twoim linku. – lkessler

+0

jak masz pojęcie, jak długo może być wyjście, użyj spakowanej tablicy [1..n] char dla bufora. Przeprowadź @CharArray [1] jako wskaźnik. –

+0

Doskonała wskazówka! (StrFormatByteSizeW) –

5

Nie dokładnie to, co jesteś po, ale mam funkcję w mojej bibliotece, które mogą dać ci pomysł, jak rozwiązać ten:

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

Gdyby nie pozostałe 1000 na być również na 1024? Ale dość zwięzłe. – lkessler

+0

Tak, technicznie powinno być 1024x1024x ... ale zostało to napisane jakiś czas temu dla konkretnego serwera wideo. Zamieszczony jako prosty przykład – Gerard

+0

Jeśli podzielisz przez 1024, powinieneś także użyć jednostek standardowych ISO TiB, GiB, MiB i KiB. – dummzeuch

0

To z mojej jednostki dzlib 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; 
Powiązane problemy