You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从指定位置向ListView第三列添加文件大小数据?

问题排查与修复方案

首先,你的代码核心问题是没有把文件大小对应到ListView中已有的文件条目上,而是把所有大小作为新的ListItem添加,同时还有内存管理和逻辑上的疏漏。下面一步步拆解问题并给出修复方案:

一、核心逻辑错误:文件大小与条目不匹配

原代码中,你先添加文件夹、文件条目,然后单独把大小作为新行添加,这完全不符合"第三列显示大小"的需求。正确的逻辑应该是:

  • 添加文件夹条目时,第三列可以填"-"或者空(文件夹本身无文件大小属性)
  • 添加文件条目时,直接把对应的大小添加到该条目的SubItems第二个位置(第一列是名称,第二列是类型,第三列就是大小)

二、具体代码修复步骤

1. 修复全局变量ListSize的内存泄漏与逻辑错误

全局变量ListSize在GetFiles中重复创建却从未释放,会导致严重内存泄漏。我们去掉全局变量,让GetFiles通过参数传出大小列表:

function GetFiles(const FileName, Ext: String; out FileSizes: TStrings): TStrings;
Var
  SearchFile: TSearchRec;
  FindResult: integer;
  ListFiles: TStrings;
  FullPath: string;
begin
  ListFiles := TStringlist.Create;
  FileSizes := TStringlist.Create;
  FindResult := FindFirst(FileName + Ext, faAnyFile, SearchFile);
  try
    While FindResult = 0 do
    begin
      // 排除目录和.、..
      if (SearchFile.Attr and faDirectory) = 0 then
      begin
        FullPath := FileName + SearchFile.Name;
        ListFiles.Add(SearchFile.Name);
        FileSizes.Add(FileSizeStr(FullPath));
      end;
      FindResult := FindNext(SearchFile);
    end;
  finally
    FindClose(SearchFile)
  end;
  Result := ListFiles;
end;

2. 修复ListView的填充逻辑

修改btn1Click,让文件大小对应到正确列,同时确保ListView是报表模式并添加好三列(可在设计时设置,也可代码添加):

procedure TForm1.btn1Click(Sender: TObject);
var
  L: TListItem;
  vListFolders, vListFiles, vListSize: TStringlist;
  i: integer;
begin
  LV1.Clear;
  // 确保ListView为报表模式并配置列
  LV1.ViewStyle := vsReport;
  while LV1.Columns.Count < 3 do
    LV1.Columns.Add;
  LV1.Columns[0].Caption := '名称';
  LV1.Columns[1].Caption := '类型';
  LV1.Columns[2].Caption := '大小';
  // 调整列宽适配显示
  LV1.Columns[0].Width := 200;
  LV1.Columns[1].Width := 80;
  LV1.Columns[2].Width := 100;

  vListFolders := TStringlist.Create;
  try
    vListFolders.Text := ListFolders('C:\');
    // 添加文件夹条目
    for i := 0 to vListFolders.Count - 1 do
    begin
      L := LV1.Items.Add;
      L.Caption := vListFolders.Strings[i];
      L.SubItems.Add('Folder');
      L.SubItems.Add('-'); // 文件夹大小列显示"-"
    end;
  finally
    vListFolders.Free;
  end;

  vListFiles := TStringlist.Create;
  vListSize := TStringlist.Create;
  try
    vListFiles := GetFiles('C:\', '*.*', vListSize);
    // 添加文件条目并对应大小到第三列
    for i := 0 to vListFiles.Count - 1 do
    begin
      L := LV1.Items.Add;
      L.Caption := vListFiles.Strings[i];
      L.SubItems.Add('File');
      L.SubItems.Add(vListSize.Strings[i]);
    end;
  finally
    vListFiles.Free;
    vListSize.Free;
  end;
end;

3. 修复ListFolders函数的逻辑错误

原函数会包含.和..目录,且字符串拼接效率低,修改如下:

function ListFolders(const Directory: String): string;
var
  SearchRec: TWin32FindData;
  FindHandle: THandle;
  Dirlist: TStrings;
begin
  Dirlist := TStringList.Create;
  try
    FindHandle := FindFirstFile(PChar(Directory + '*.*'), SearchRec);
    if FindHandle <> INVALID_HANDLE_VALUE then
    begin
      repeat
        // 仅保留真实目录,排除.和..
        if ((SearchRec.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) <> 0)
          and (SearchRec.cFileName <> '.')
          and (SearchRec.cFileName <> '..') then
        begin
          Dirlist.Add(SearchRec.cFileName);
        end;
      until not FindNextFile(FindHandle, SearchRec);
      Winapi.Windows.FindClose(FindHandle);
    end;
    Result := Dirlist.Text;
  finally
    Dirlist.Free;
  end;
end;

4. 优化FileSizeStr函数的显示精度

原函数用%f会显示过多小数位,改为保留两位小数更美观,同时添加文件共享模式避免占用报错:

function FileSizeStr(const FileName: string): string;
const
  K = Int64(1024);
  M = K * K;
  G = K * M;
  T = K * G;
var
  size: Int64;
  handle: integer;
begin
  handle := FileOpen(FileName, fmOpenRead or fmShareDenyNone);
  if handle = -1 then
    Result := '无法打开文件'
  else
  try
    size := FileSeek(handle, Int64(0), 2);
    if size < K then
      Result := Format('%d bytes', [size])
    else if size < M then
      Result := Format('%.2f KB', [size / K])
    else if size < G then
      Result := Format('%.2f MB', [size / M])
    else if size < T then
      Result := Format('%.2f GB', [size / G])
    else
      Result := Format('%.2f TB', [size / T]);
  finally
    FileClose(handle);
  end;
end;

三、结合远程场景的适配建议

根据你补充的远程管理应用逻辑,需确保文件名和大小的顺序完全对应,接收完数据后填充ListView时,把每个文件条目对应的大小添加到第三列:

// 假设已接收解析得到文件列表FileList和大小列表SizeList
for i := 0 to FileList.Count - 1 do
begin
  L := (L2.SubItems.Objects[4] as TForm3).ListView1.Items.Add;
  L.ImageIndex := 1; // 设置文件图标索引
  L.Caption := FileList.Strings[i];
  L.SubItems.Add('File');
  if i < SizeList.Count then
    L.SubItems.Add(SizeList.Strings[i])
  else
    L.SubItems.Add('未知');
end;

这样就能确保每个文件条目第三列显示对应的大小了。


内容的提问来源于stack exchange,提问作者user9672569

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 04:24:15