简体   繁体   English

Delphi函数显示Windows的字节数

[英]Delphi Function to Display Number of Bytes as Windows Does

This is a simple one (I think). 这是一个简单的(我认为)。

Is there a system built in function, or a function that someone has created that can be called from Delphi, that will display a number of bytes (eg a filesize), the way Windows displays in a file's Properties box? 是否有一个内置函数的系统,或某人创建的可以从Delphi调用的函数,它将显示一些字节(例如文件大小),Windows在文件的属性框中显示的方式?

eg This is how Windows property box displays various sizes: 例如,这是Windows属性框显示各种大小的方式:

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

The display is smart about using bytes, KB, MB or GB, and shows only 3 significant digits for the KB, MB and GB. 显示屏使用字节,KB,MB或GB非常智能,并且仅显示KB,MB和GB的3位有效数字。 It then follows that by displaying the exact number of bytes in parenthesis with commas separating the thousands. 然后通过用逗号分隔数千个括号显示括号中的确切字节数。 It is a very nice display, well thought out. 这是一个非常好的显示,经过深思熟虑。

Does anyone know of such a function? 有谁知道这样的功能?


Edit: I'm very surprised there wasn't a function for this. 编辑:我很惊讶没有这个功能。

Thanks for your helpful ideas. 谢谢你的有用的想法。 I've come up with this, which seems to work: 我想出了这个,这似乎有效:

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;

This is probably good enough, but is there anything better? 这可能已经够好了,但有什么更好的吗?

See the following functions, all in the shlwapi library . 请参阅shlwapi库中的以下函数。

Any of them will give you the first portion of your desired display format. 他们中的任何一个都会为您提供所需显示格式的第一部分。 Check the documentation or write your own tests to confirm that they give the conversions you expect regarding whether a megabyte consists of 1000 or 1024 kilobytes. 检查文档或编写您自己的测试,以确认它们是否提供了您预期的兆字节是否包含1000或1024千字节的转换。 For the second part of your display format, you can start with the answers to another Stack Overflow question: 对于显示格式的第二部分,您可以从另一个Stack Overflow问题的答案开始:

But perhaps that question is the wrong avenue to go down since all the suggestions there, as well as FloatToStrF , fail at the upper limits of Int64 . 但也许这个问题是错误的途径,因为那里的所有建议,以及FloatToStrF ,都在Int64的上限失败了。 You'll lose a few bytes, but I consider those pretty important bytes since the purpose of the second value in that display format is to provide an exact number. 你将丢失几个字节,但我认为这些非常重要的字节,因为该显示格式中第二个值的目的是提供一个确切的数字。

Once you have all the pieces, glue them together. 一旦你有了所有的碎片,将它们粘在一起。 I'm using a hypothetical IntToStrCommas function here, and if you want to implement that as FloatToStrF , go ahead. 我在这里使用假设的IntToStrCommas函数,如果你想将它实现为FloatToStrF ,请继续。

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;

Not exactly what you're after but I have a function in my library that may give you an idea how to tackle this one: 不完全是你想要的,但我在我的库中有一个功能,可以让你知道如何解决这个问题:

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;

This is from my dzlib unit u_dzConvertUtils : 这是来自我的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;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM