【问题标题】:Delphi, FindNext return error 18 even there is a folderDelphi,FindNext即使有文件夹也返回错误18
【发布时间】:2012-04-23 05:53:21
【问题描述】:

来自冰岛的问候!

首先,我用谷歌和这里都搜索过,没有结果。

我在 Delphi 中写作,并且在 Delphi 方面有几年的经验(在 Pascal 方面超过 30 年)

这些年来,我构建了各种文件实用程序的程序,并在几乎所有此类应用程序中使用了 FindFirst 和 FindNext 功能。今天我正在使用我编写的旧文件实用程序,发现它不能 100% 工作

在目录名称变得有点奇怪之前没关系,即名称内部有几个句点。故事是我正在安装 Wamp,那里的一些文件夹用这种奇怪的方法命名。

As: "c:\wamp\apps\phpmyadmin3.4.5"
    "c:\wamp\apps\sqlbuddy1.3.3"
    "c:\wamp\apps\webgrind1.0 etc"

当我进行调试时,我发现 Findnext 刚刚返回错误 18,这与 FindNext 在找不到更多文件时返回的错误相同。

我尝试过 FindFirstFile 和 FindNextFile,结果相同。我正在考虑尝试 API FindNextFileEx,如果这与长文件名有关,但不是那么乐观..

我还注意到这些文件夹中的属性不是 16 (hex10) 而是 8208 (8192+16),但它与这个问题没有任何关系,例如我可以屏蔽 (AND) attr 与 $00FF 等。

PROCEDURE TForm_Leit.Finna_Dir (Str_InnDir : STRING);
  VAR
    S_Rec1           : TSearchRec;
    Bo_Buid          : BOOLEAN;
BEGIN
  .
  .
  .
  //Find Dir part
  IF (FindFirst (Str_Inndir+'\*.', faDirectory, S_Rec1) = 0) THEN
  REPEAT
    Bo_Buid := FALSE;
    IF ((S_Rec1.Name = '.') OR (S_Rec1.Name = '..')) THEN
    REPEAT
      Bo_Buid := FindNext (S_Rec1) <> 0;
    UNTIL NOT((S_Rec1.Name = '.') OR (S_Rec1.Name = '..')) OR (Bo_BUid);

    IF NOT(Bo_Buid) THEN
      Finna_Dir (Str_Inndir+'\'+S_Rec1.Name); //Recursion

  UNTIL (FindNext (S_Rec1) <> 0);
END;

【问题讨论】:

  • 这是一个需要代码的问题。单击编辑链接并在问题中添加一些代码。
  • 为了避免泄漏,FindClose(S_Rec1);必须添加声明。参见示例:FindFirst_(Delphi).
  • @user - 您介意就我发布的答案提供一些反馈吗?谢谢..
  • @LU RD 是的..我在发布代码时确实注意到了..我通常在我的商业应用程序中使用 Findclose,这些实用程序很旧而且通常写得不好..但使用仅限于仅限我,因为我不分发 file utilite 的游戏。
  • @Sertac Akyuz .. 是的,我会的,你的解决方案在我脑海里敲响了警钟,我会试试这个,我很乐观你会发现......因为搜索字符串仅限于名称没有时期..哇!让我测试一下并尽快给你反馈。

标签: delphi


【解决方案1】:

您使用的模式 ('\*.') 仅与其中没有句点的文件和目录名称匹配(这也意味着文件没有扩展名)。尝试:

IF (FindFirst (Str_Inndir+'\*', ...


稍微详细地说,VCL 的“Find..”函数是底层 API 的“Find..”函数的包装器,它并不关心您是否要搜索文件或文件夹(“Attr”参数你可以传递给sysutils.FindFirst是VCL提供的一个工具,VCL只能通过过滤来影响搜索结果)。因此,对于文件或文件夹,使用“*.”模式的结果不会有所不同。如果模式不能返回带有句点的文件名,那么它也不能返回带有句点的文件夹。

参数的用法与dir命令相同。从命令提示符导航到您的“..\apps”文件夹,如果您发出&gt;dir *.,您将不会看到列出的问题中的文件夹。

您可以查看并尝试以下示例代码中的不同“模式”,该示例代码仅使用 API 枚举文件,以了解不同的通配符如何影响搜索结果。

var
  Data: TWIN32FindData;

procedure ListFiles(const Path, Pattern: string; List: TStrings);

  function IsDot: Boolean;
  begin
    Result := (string(Data.cFileName) = '.') or (Data.cFileName = '..');
  end;

  function IsDirectory: Boolean;
  begin
    Result := Bool(Data.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY);
  end;

  procedure PutFileName;
  begin
    if not IsDot then begin
      if IsDirectory then
        List.Add(Path + '\' + Data.cFileName + ' <dir>')
      else
        List.Add(Path + '\' + Data.cFileName);                                  //'
    end;
  end;

var
  FindHandle: THandle;
begin
  FindHandle := FindFirstFile(PChar(Path + Pattern), Data);
  if FindHandle <> INVALID_HANDLE_VALUE then
    try
      PutFileName;

      while FindNextFile(FindHandle, Data) do begin
        PutFileName;
        if (not IsDot) and IsDirectory then
          ListFiles(Path + '\' + Data.cFileName, Pattern, List);                //'
      end;

    finally
      windows.FindClose(FindHandle);
    end;
end;

procedure TForm1.Button1Click(Sender: TObject);
const
  Pattern = '\*';
begin
  Memo1.Clear;
  ListFiles('..sometestdirectory..', Pattern, Memo1.Lines);
end;

【讨论】:

  • 是的!!!你在哪里对..真是一团糟,我已经习惯使用 *.即使每次我试图弄清楚这一点时都在看它,我也没有看到它!我如何给你这个答案的功劳?那么这里的其他人尽力帮助我呢?
  • @user - 很高兴能够提供帮助!请参阅大卫的评论以了解如何接受答案。当您拥有 15 个声望点时,您就可以对帖子进行投票了。
【解决方案2】:

有不同的方法可以避免这个问题:

1/ 使用完整过滤器(更新用于文件夹)

  FA_ALL_FILES_EX = faNormalFile +
    faReadOnly + faHidden + faSysFile + faArchive + faTemporary + faSparseFile
    + faReparsePoint + faCompressed + faOffline + faNotContentIndexed + faEncrypted;  

  // $80 must be added because if the file's archive attribute is not set,
  // then FindFirst return [FindoInfo.Attr = 128]  ...

2/ 使用Delphi2009+单元IOUtils的最新函数:IOUtils.TDirectory.GetDirectories() http://docwiki.embarcadero.com/VCL/XE2/en/IOUtils.TDirectory.GetDirectories

【讨论】:

  • 好的..我将尝试从 2009 年检索 IOutils,我目前使用的是 Delphi 7
【解决方案3】:

你使用 faAnyFile 常量吗?这是错误的,并且不包含所有必要的值。定义(并使用)一个值为 $FFFF 的新常量。

【讨论】:

  • 我确实尝试过.. 我确实使用过:Findfirst (Str_Inndr+'*.', faDirectory+$ff00, S_Rec) 等,但我认为它是一样的!
猜你喜欢
  • 2020-06-08
  • 2011-06-21
  • 2013-12-25
  • 2020-03-20
  • 2021-03-24
  • 1970-01-01
  • 2021-01-13
  • 2022-07-12
  • 1970-01-01
相关资源
最近更新 更多