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

Posted

技术标签:

【中文标题】获取文件大小 > 然后获取总大小?【英文标题】:Getting File Sizes > And then Getting the Total Size? 【发布时间】:2011-11-26 18:21:44 【问题描述】:

这应该很容易,但我似乎无法正确处理,因为我似乎在混淆自己并在字符串、整数和浮点数等之间进行转换。

基本上,我在 TListView 的一列中填充 FileNames,在另一列中将文件大小返回到相应的 FileName。我正在使用从here 找到的一个相当简洁的函数,它看起来像这样:

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 可能会像这样填充:

现在在标签数据大小中,我想返回列表视图中文件的总大小,因此在本例中,大小列中的值需要相加才能返回总大小,例如:

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 函数进行了更简洁的更新,效果很好:

【问题讨论】:

【参考方案1】:

将“获取文件信息”与“格式化大小字符串”分离成两个单独的函数。文件信息函数获取文件大小并将其添加到运行总计中,然后调用格式化函数将简单整数转换为“nice”字符串。

【讨论】:

这么简单的事情我不知道为什么我从来没有想到过,而不是不断地尝试转换值,而且我总是让事情变得比需要的更困难!让我试试这个方法.. +1。发布了一个单独的答案,其中包含问题的文件大小部分的一些代码。【参考方案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 提供了我从中学到的其他信息,我现在从您所说的有关原始代码缺陷的内容中了解更多。

以上是关于获取文件大小 > 然后获取总大小?的主要内容,如果未能解决你的问题,请参考以下文章

获取下载文件的大小

Unix命令行:如何获取最近30天修改文件的总大小

获取 GCS 中文件夹的文件数和总大小的最快方法?

C++通过文件指针获取文件大小

请教java如何实现获取一段mp3的总时长

有没有办法使用Javascript实时获取传输到页面的文件的总大小?