获取文件大小 > 然后获取总大小?

4
这应该很容易,但我似乎总是把自己搞糊涂,将字符串、整数和浮点数之类的东西互相转换。

基本上,我正在用文件名填充 TListView 中的一列,并在另一列返回对应的文件大小。我使用了一个非常棒的函数,可以在这里找到,它看起来像这样:
function FileSizeStr ( filename: string ): string;
const
//   K = Int64(1000);     // Comment out this line OR
  K = Int64(1024);     // Comment out this line
  M = K * K;
  G = K * M;
  T = K * G;
var
  size: Int64;
  handle: integer;
begin
  handle := FileOpen(filename, fmOpenRead);
  if handle = -1 then
    result := 'Unable to open file ' + filename
  else try
    size := FileSeek ( handle, Int64(0), 2 );
    if size < K then result := Format ( '%d bytes', [size] )
    else if size < M then result := Format ( '%f KB', [size / K] )
    else if size < G then result := Format ( '%f MB', [size / M] )
    else if size < T then result := Format ( '%f GB', [size / G] )
    else result := Format ( '%f TB', [size / T] );
  finally
    FileClose ( handle );
  end;
end;

这会返回像“235.40 KB”这样的值。
因此,通过上述方法,我的TListView可以被填充如下所示:
现在,在Label Data Size中,我希望返回Listview中文件的总大小,因此在此示例中,需要将Size列中的值相加以返回Total Size,类似于以下内容:
1.28 MB + 313.90 KB + 541.62 KB + 270.96 KB
显然,不能仅仅这样添加,因为这些值包含小数点,有些值可能是KB,而其他值可能是MB等。这是我的问题,我无法想出一个简单的解决方案,来获取(获取)文件的总大小,然后以与显示相同的格式化字符串返回它。
我真的很感激一些关于如何处理此类数据的见解或提示,我只是在不同的转换中不断让自己感到困惑,不确定用哪种方式完成此操作。
提前谢谢 :)
更新1:
根据Marc B的建议,我将函数更改为以下内容,它似乎起作用:
var
  iFileSize: Int64;

implementation

function GetSizeOfFile(FileName: string): Int64;
var
  Handle: Integer;
begin
  Handle := FileOpen(FileName, fmOpenRead);

  if Handle = -1 then
    MessageDlg('Unable to open file ' + FileName, mtError, [mbOk], 0)
  else try
    iFileSize := iFileSize + FileSeek(Handle, Int64(0), 2);
  finally
    FileClose(Handle);
  end;

  Result := iFileSize;
end;

function FormatFileSize(AValue: Int64): string;
const
  K = Int64(1024);
  M = K * K;
  G = K * M;
  T = K * G;
begin
  if AValue < K then Result := Format ( '%d bytes', [AValue] )
  else if AValue < M then Result := Format ( '%f KB', [AValue / K] )
  else if AValue < G then Result := Format ( '%f MB', [AValue / M] )
  else if AValue < T then Result := Format ( '%f GB', [AValue / G] )
  else Result := Format ( '%f TB', [AValue / T] );
end;

如果其他人需要的话,这可能会很有用 :)

更新2

此外,请参见Ken White发布的答案,其中提供了更有价值的信息和更清晰的GetSizeOfFile函数更新,它非常有效:

enter image description here

2个回答

6
将“获取文件信息”和“格式化大小字符串”分开成两个独立的函数。文件信息函数获取文件大小并将其添加到运行总数中,然后调用格式化函数将简单整数转换为“漂亮”的字符串。请保留HTML标记。

这么简单的东西,我不知道为什么我从来没有想过,而是不断地尝试转换值,并且像我总是那样使事情变得更加困难!让我试试这种方法。 - user741875
+1。针对文件大小部分的问题,我发布了一个带有代码的单独答案。 - Ken White

2
最简单的方法是更改您的函数以返回文件大小,并使用另一个函数来格式化结果。
我知道您已经接受了一个答案,但您发布的更新代码存在一些问题(其中一个问题在原始版本中也存在)。
首先,您获取文件大小的方法非常慢,特别是如果您要使用它来列出很多文件。实际上,您正在打开文件,将文件指针移动到文件末尾以获取大小,然后关闭文件。此外,如果文件被其他应用程序专有地打开,则可能会失败。
其次,您的新版本GetSizeOfFile存在逻辑错误。您每次都会将值添加到全局累加值中(这是您想要的),但您还会返回该新全局值,而根据您发布的示例图像,您不希望这样做。
这是一个可以替换GetSizeOfFile并与示例用法一起使用的示例:
function GetSizeOfFile( const FileName: String ): Int64;
var
  Rec : TSearchRec;
begin
  Result := 0;
  if (FindFirst(FileName, faAnyFile, Rec) = 0) then
  begin
    Result := Rec.Size;
    FindClose(Rec);
  end;
end;

使用示例:

var
  FileSize: Int64;
  FileSizeString: string;
begin
  { Whatever code  }
  FileSize := GetSizeOfFile(SomeFileName);
  iFileSize := iFileSize + NewSize;
  FileSizeString := FormatFileSize(NewSize);

  { Add your file to your ListView.}
end;

非常感谢Ken提供的额外信息,我从中学到了很多。现在我更加理解你所说的原始代码中存在的缺陷。 - user741875

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接