2009-08-17 50 views
6

这是一个简单的(我认为)。德尔福函数显示Windows的字节数

是否有一个系统内置函数,或者某人创建了一个可以从Delphi调用的函数,显示大量字节(例如文件大小),这与Windows在文件的“属性”框中显示的方式相同?

例如这是由于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) 

显示的是聪明使用字节,KB,MB或GB,并且只显示3为KB,MB和GB显著数字。然后通过以逗号分隔数千的方式在圆括号中显示确切的字节数。这是一个很好的展示,经过深思熟虑。

有谁知道这样的功能?


编辑:我很惊讶没有这个功能。

感谢您的帮助。我想出了这个,这似乎工作:

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; 

这可能是够好,但有什么更好吗?

回答

12

请参见下面的功能,都在shlwapi library

他们中的任何一个都会给你所需显示格式的第一部分。检查文档或编写自己的测试,以确认他们是否给出了您期望的有关一个兆字节是由1000或1024千字节组成的转换。为了您的显示格式的第二部分,你可以用回答另一个堆栈溢出的问题开始:(他真的问如何插入逗号,没有专门关于金钱)

但也许这个问题是错误的方法,因为所有的建议,以及FloatToStrF,失败的上限Int64。你会丢失几个字节,但我认为这些非常重要的字节,因为在显示格式中第二个值的目的是提供一个确切的数字。

一旦你有所有的作品,将它们粘合在一起。我在这里使用假设的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; 
+1

StrFormatByteSize64看起来似乎是Windows用于第一部分。但是从Delphi调用该函数需要设置一个缓冲区 - 不太好。对于第二部分,floattostrf似乎比链接中的解决方案更好。 – lkessler 2009-08-17 04:31:24

+0

,因为您有一些想法可以输出多长时间,使用char的压缩数组[1..n]作为缓冲区。通过@CharArray [1]作为指针。 – 2009-08-17 08:34:31

+0

优秀的提示! (StrFormatByteSizeW) – 2015-03-24 19:46:28

5

不正是你追求的,但我有我的库中的函数,可能会给你一个想法如何解决这一个:

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

如果不是其他1000的也有1024的?但相当简洁。 – lkessler 2009-08-17 04:34:07

+0

是的,从技术上说它应该是1024x1024 ...但是这是前一段时间写的一个特定的视频服务器。作为简单示例发布 – Gerard 2009-08-17 04:42:32

+0

如果除以1024,则还应该使用ISO标准单元 TiB,GiB,MiB和KiB。 – dummzeuch 2009-08-17 07:02:22

0

这是从我的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;