Pregunta

Esto es muy simple (creo).

¿Hay un sistema incorporado en la función, o una función que alguien ha creado que se puede llamar desde Delphi, que mostrará un número de bytes (por ejemplo, un tamaño de archivo), la forma en que Windows muestra en el cuadro de propiedades de un archivo?

por ejemplo. Así es como cuadro de propiedades de Windows muestra diversos tamaños:

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

La pantalla es inteligente acerca del uso de bytes, KB, MB o GB, y muestra sólo 3 dígitos significativos para el KB, MB y GB. De esto se deduce que, visualizando el número exacto de bytes entre paréntesis por comas separar los miles. Es una pantalla muy agradable, bien pensado.

¿Alguien sabe de una función de este tipo?


Edit: Estoy muy sorprendido de que no había una función para este

.

Gracias por sus ideas útiles. Yo he llegado con esto, que parece funcionar:

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;

Esto es probablemente lo suficientemente bueno, pero ¿hay algo mejor?

¿Fue útil?

Solución

Vea las siguientes funciones, todo en el shlwapi biblioteca .

Cualquiera de ellos le dará la primera parte de su formato de visualización deseado. Consulte la documentación o escribir sus propias pruebas para confirmar que se dan las conversiones que se pueden esperar con respecto a si un megabyte consiste en 1000 o 1024 kilobytes. Para la segunda parte de su formato de visualización, se puede comenzar con las respuestas a otra pregunta de desbordamiento de pila:

Pero tal vez esa pregunta es la vía equivocada para bajar desde allí todas las sugerencias, así como FloatToStrF, fallar en los límites superiores de Int64. Si no se pierden unos pocos bytes, pero considero que estos bytes muy importantes ya que el propósito del segundo valor en ese formato de presentación es el de proporcionar un número exacto.

Una vez que tenga todas las piezas, pegarlas. Estoy usando una función IntToStrCommas hipotética aquí, y si se desea implementar que a medida que FloatToStrF, adelante.

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;

Otros consejos

No es exactamente lo que está buscando, pero tengo una función en mi biblioteca que puede dar una idea de cómo hacer frente a este:

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;

Esto es de mi unidad de 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;
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top