Delphi FMX 10.3:在多平台应用程序中获取文件属性的问题

时间:2019-12-12 14:42:46

标签: delphi filesystems firemonkey

我正在寻求将一些Delphi代码转换为从操作系统中提取文件属性,从Windows平台的悠久实践到Android平台的新实现。

我发现,尽管Delphi平台的实现使用功能FindFirst()FindNext()不会出现问题,并且允许从TSearchRec参数获取文件属性,但是这种方法没有似乎不适用于Android平台。

因此,我需要查找跨平台功能来获取文件和目录属性。使用System.IOUtils记录类型TDirectoryTFile的方法可以获得几种属性。但是出于某种原因,这些文件似乎没有包括一种获取文件大小(以字节为单位)的方法。

因此,我尝试通过给定路径名的文件创建一个TFileStream对象,然后从TFileStream.Size属性中获取文件大小来获取文件大小。当文件尚未打开时,此方法有效。但是,如果文件已打开,则会引发异常。

那么,下一个问题是如何在调用TFileStream.Create()之前查明文件是否已打开。这应该很简单,但是我不记得该怎么做。因此,我尝试了以下全局过程:

procedure FXGetFileSize(FilePathname: string; var FileInUse: Boolean;
                            var Size: int64);
var
  FileStream: TFileStream;
begin
  try
    FileStream:= TFileStream.Create(FilePathname, fmOpenRead);
    try
      FileInUse:= False;
      Size:= FileStream.Size;
    finally
      FileStream.Free;
    end;
  except
    on E: Exception do
      begin
        FileInUse:= True;
        Size:= 0;
        FileStream.Free;
      end;
  end;
end;

我从以下方法中调用此过程:

procedure TFolder.ReadFX (Pathname: string; Recurse: Boolean);
{Reads details of folder file components in a folder  into a TFolder data structure – cross-platform version}
var
    Separator: char;
    FolderPaths: TStringDynArray;
    FilePathNames: TStringDynArray;
    i: integer;
    FolderPathI: string;
    FilePathnameI: string;
    SubFolder: TFolder;
    SubFileCpt: TFileCpt;
    SubFileCptIndex: integer;
    FolderCptName: string;
    Datetime: TDatetime;
    FileInUse: Boolean;
    FileSize: int64;
  begin
    Separator:= TPath.DirectorySeparatorChar;
    FCount:= 0;
    FCumSize:= 0;
    FCumFileCount:= 0;
    FCumFolderCount:= 1;
    {Extract list of subfolders in directory:}
    FolderPaths:= TDirectory.GetDirectories(Pathname);
    {Create a TFolder object for each subfolder:}
    for i:= 0 to High(FolderPaths) do
      begin
        FolderPathI:= FolderPaths[i];
        if TDirectory.Exists(FolderPathI) then
          begin
            try
              {Create TFolder object for subfolder i:}
              SubFolder:= TFolder.Create;
              AddFolderCpt(SubFolder, SubFileCptIndex);
              {Assign TFolder properties:}
              FolderCptName:= StringReplace(FolderPathI, (Pathname + Separator), '', [rfIgnoreCase]);
              Subfolder.Name:= FolderCptName;
              {Subfolder.Name:= Path; }
              Subfolder.FDateTime:= TDirectory.GetLastWriteTime(FolderPathI);
              {Recursively process subfolder:}
              if Recurse then
                Subfolder.Read(FolderPathI, Recurse);
              {Compute aggregate properties:}
              FCumSize:= FCumSize + SubFolder.FCumSize;
              FCumFileCount:= FCumFileCount + SubFolder.FCumFileCount;
              FCumFolderCount:= FCumFolderCount + SubFolder.FCumFolderCount;
            except
              on E: Exception do
                begin
                  E.Message:= 'Error in TFolder.ReadFX processing folder "'
                     + FolderPathI + '"' + #13#10
                     + '(' + E.Message + ')';
                end;
              end;
            end;
        end;
    {Get list of files in directory:}
    FilePathNames:= TDirectory.GetFiles(Pathname);
    {Create TFileCpt objects for each child file:}
    for i:= 0 to High(FilePathnames) do
      begin
        FilePathnameI:= FilePathnames[i];
        if (FilePathnameI<> '.') and (FilePathnameI<>'..') then
          begin
            try
              {$ifdef MSWINDOWS}
              if not ([TFileAttribute.faHidden, TFileAttribute.faSystem] <=
                                    TFile.GetAttributes(FilePathnameI)) then
              {$endif}
                begin
                  FXGetFileSize(FilePathnameI, FileInUse, FileSize);      {***}
                  {Create a TFileCpt object corresponding to FilePathnameI:}
                  SubFileCpt:= TFileCpt.Create;
                  AddFolderCpt(SubFileCpt, SubFileCptIndex);
                  {Assign TFileCpt properties:}
                  SubFileCpt.FName:= TPath.GetFileName(FilePathnameI);
                  SubFileCpt.FSize:= FileSize;
                  SubFileCpt.FDateTime:= TFile.GetLastWriteTime(FilePathnameI);
                  FCumSize:= FCumSize + FileSize;
                  FCumFileCount:= FCumFileCount + 1;
                end;
            except
              on E: Exception do
                begin
                  E.Message:= 'Error in TFolder.ReadFX processing file "'
                     + FilePathnameI + '"' + #13#10
                     + '(' + E.Message + ')';
                end;
            end;
          end;
      end;
  end;

不幸的是,当我在Windows 7上为TFolder.ReadFX()调用Pathanme= ‘C:\\Users\User XXX'时,遇到可能由Windows OS打开的打开文件时,总是会抛出运行时异常。

最后,有人可以解决以下问题吗?

  1. 如何在不打开文件流的情况下获取文件大小

  2. 如何确定文件是否已经/正在使用

  3. 对于文件夹,如何从文件夹路径中提取最低级别的文件夹名称,而无需手动解析路径。

0 个答案:

没有答案