我正在寻求将一些Delphi代码转换为从操作系统中提取文件属性,从Windows平台的悠久实践到Android平台的新实现。
我发现,尽管Delphi平台的实现使用功能FindFirst()
和FindNext()
不会出现问题,并且允许从TSearchRec
参数获取文件属性,但是这种方法没有似乎不适用于Android平台。
因此,我需要查找跨平台功能来获取文件和目录属性。使用System.IOUtils
记录类型TDirectory
和TFile
的方法可以获得几种属性。但是出于某种原因,这些文件似乎没有包括一种获取文件大小(以字节为单位)的方法。
因此,我尝试通过给定路径名的文件创建一个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打开的打开文件时,总是会抛出运行时异常。
最后,有人可以解决以下问题吗?
如何在不打开文件流的情况下获取文件大小
如何确定文件是否已经/正在使用
对于文件夹,如何从文件夹路径中提取最低级别的文件夹名称,而无需手动解析路径。